Upgrade to Pro — share decks privately, control downloads, hide ads and more …

MySQLの容量とか圧縮まわり

 MySQLの容量とか圧縮まわり

Satoshi MITANI

September 03, 2019
Tweet

More Decks by Satoshi MITANI

Other Decks in Technology

Transcript

  1. ⾃⼰紹介 5 • 三⾕ 智史(Twitter: @mita2) • MySQL DBA @

    どっかのポータルサイト • どきどきブログを書いてます http://mita2db.blogspot.com/
  2. 1. 断⽚化 • 物理ファイルは(⾃動的に)縮まらない 10 # ls -alh sbtest/sbtest1.ibd -rw-r-----

    mysql mysql 240M Aug 28 sbtest/sbtest1.ibd mysql> DELETE FROM sbtest.sbtest1; Query OK, 1000000 rows affected (11.74 sec)
  3. 1. 断⽚化 • テーブルをリビルドすると解放される 11 $ ls -alh sbtest/sbtest1.ibd -rw-r-----

    mysql mysql 128K Aug 28 sbtest/sbtest1.ibd mysql> ALTER TABLE sbtest.sbtest1 ENGINE=InnoDB; Query OK, 0 rows affected (0.06 sec) Records: 0 Duplicates: 0 Warnings: 0
  4. 2. 論理サイズは統計情報に基づく • 論理サイズ • SHOW TABLE STATUS • information_schema.TABLES

    12 mysql> SELECT TABLE_NAME, DATA_LENGTH, INDEX_LENGTH, DATA_FREE FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'sbtest1'; +------------+-------------+--------------+-----------+ | TABLE_NAME | DATA_LENGTH | INDEX_LENGTH | DATA_FREE | +------------+-------------+--------------+-----------+ | sbtest1 | 225132544 | 16269312 | 4194304 | +------------+-------------+--------------+-----------+ 1 row in set (0.00 sec)
  5. 2. 統計情報 • サンプリングをもとに全体量を推定 • → 誤差 • サンプリングするページ数 •

    innodb_stats_persistent_sample_pages をベースに計算 13 https://dev.mysql.com/doc/refman/5.6/ja/innodb-analyze-table-complexity.html より
  6. MySQL 8から⼊った、余計な︖ヤーツ 15 mysql> DELETE FROM sbtest.sbtest1 ; Query OK,

    1000000 rows affected (9.53 sec) mysql> SELECT TABLE_ROWS FROM information_schema.tables WHERE table_name = 'sbtest1'; +------------+ | TABLE_ROWS | +------------+ | 986400 | +------------+ 1 row in set (0.01 sec)
  7. お掃除 • 不要なテーブル、レコード • PKで⼩分けにして消し込み • ⼤きなロックの回避 • レプリケーション遅延の回避 21

    mysql> SELECT id FROM mytable WHERE created_at < ‘2019-08-30’; mysql> DELETE FROM mytable WHERE id IN (…)
  8. お掃除 • 過去に⼀度も使われてないインデックス 22 mysql> SELECT * FROM sys.schema_unused_indexes; +---------------+-------------+------------+

    | object_schema | object_name | index_name | +---------------+-------------+------------+ | sbtest | sbtest1 | k_1 | | sbtest | sbtest2 | k_2 | | sbtest | sbtest3 | k_3 | +---------------+-------------+------------+ 6 rows in set (0.02 sec)
  9. お掃除 23 • 冗⻑なインデックス CREATE TABLE `sbtest1` ( `id` int(11)

    NOT NULL AUTO_INCREMENT, `k` int(11) NOT NULL DEFAULT '0', `c` char(120) NOT NULL DEFAULT '', `pad` char(60) NOT NULL DEFAULT '', PRIMARY KEY (`id`), KEY `k_1` (`k`), KEY `k_c_1` (`k`,`c`) ) ENGINE=InnoDB
  10. お掃除 24 mysql> SELECT * FROM sys.schema_redundant_indexes ¥G *************************** 1.

    row *************************** table_schema: sbtest table_name: sbtest1 redundant_index_name: k_1 redundant_index_columns: k redundant_index_non_unique: 1 dominant_index_name: k_c_1 dominant_index_columns: k,c dominant_index_non_unique: 1 subpart_exists: 0 sql_drop_index: ALTER TABLE `sbtest`.`sbtest1` DROP INDEX `k_1`
  11. INVISIBLE INDEX • MySQL 8.0 の新機能 • INVISIBLEにしたインデックスは使われなくなる • DROPする前の保険

    • INVISIBLE 状態でもインデックスの更新は継続 • 問題があれば、VISIBLEに戻すだけ 25 mysql> ALTER TABLE t ALTER INDEX idx_c1 [INVISIBLE|VISIBLE]; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0
  12. 圧縮 • InnoDB Table Compression • InnoDB Page Compression 27

    CREATE TABLE 〜 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=N CREATE TABLE 〜 COMPRESSION=“zlib/lz4/none”
  13. InnoDB Table Compression • ブロック数が減ることはない 30 ⾏ ⾏ ⾏ ⾏

    ⾏ ⾏ ⾏ ⾏ ⾏ ⾏ ⾏ ⾏ 間違い→ こうなる→
  14. 圧縮 • InnoDB Table Compression • InnoDB Page Compression 32

    CREATE TABLE 〜 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=N CREATE TABLE 〜 COMPRESSION=“zlib/lz4/none”
  15. InnoDB Page Compression • ⾒かけ上のサイズ • 実際使っている容量 34 $ du

    --apparent-size * 11264 no_compression.ibd 12288 page_compression.ibd $ du * 11264 no_compression.ibd 8760 page_compression.ibd
  16. InnoDB Page Compression • cpするとhole punchingされないファイルになってしまう 35 $ cp page_compression.ibd

    page_compression.copied $ du * 11216 page_compression.copied 7364 page_compression.ibd $ md5sum page_compression.copied page_compression.ibd 736477eee71dfc51e6f217945c5a6ed449c6 page_compression.copied 736577eee71dfc51e6f217945c5a6ed449c6 page_compression.ibd
  17. 主キーと容量 ⼩さな主キー 37 CREATE TABLE `sbtest1` ( `id` int(11) NOT

    NULL AUTO_INCREMENT, `k` int(11) NOT NULL DEFAULT '0', `c` char(120) NOT NULL DEFAULT '', `pad` char(60) NOT NULL DEFAULT '', PRIMARY KEY (`id`), KEY `k_1` (`k`), KEY `c_1` (`c`), KEY `pad_1` (`pad`) ) ENGINE=InnoDB CREATE TABLE `sbtest2` ( `id` int(11) NOT NULL AUTO_INCREMENT, `k` int(11) NOT NULL DEFAULT '0', `c` char(120) NOT NULL DEFAULT '', `pad` char(60) NOT NULL DEFAULT '', PRIMARY KEY (`id`,`k`,`c`), KEY `k_1` (`k`), KEY `c_1` (`c`), KEY `pad_1` (`pad`) ) ENGINE=InnoDB ⼤きな主キー
  18. 主キーと容量 496M 38 CREATE TABLE `sbtest1` ( `id` int(11) NOT

    NULL AUTO_INCREMENT, `k` int(11) NOT NULL DEFAULT '0', `c` char(120) NOT NULL DEFAULT '', `pad` char(60) NOT NULL DEFAULT '', PRIMARY KEY (`id`), KEY `k_1` (`k`), KEY `c_1` (`c`), KEY `pad_1` (`pad`) ) ENGINE=InnoDB CREATE TABLE `sbtest2` ( `id` int(11) NOT NULL AUTO_INCREMENT, `k` int(11) NOT NULL DEFAULT '0', `c` char(120) NOT NULL DEFAULT '', `pad` char(60) NOT NULL DEFAULT '', PRIMARY KEY (`id`,`k`,`c`), KEY `k_1` (`k`), KEY `c_1` (`c`), KEY `pad_1` (`pad`) ) ENGINE=InnoDB 784M
  19. 断⽚化の解消 41 もともと100万⾏だったテーブルのうち50万⾏を消した mysql> SHOW TABLE STATUS ¥G *************************** 1.

    row *************************** Name: sbtest1 Engine: InnoDB Version: 10 Row_format: Dynamic Rows: 493200 # 50万⾏ Avg_row_length: 295 Data_length: 145883136 Max_data_length: 0 Index_length: 16138240 Data_free: 116391936 # 116M
  20. 断⽚化の解消 42 $ sudo ls -alh /var/lib/mysql/sbtest total 273M drwxr-x---

    2 mysql mysql 25 Sep 12 21:41 . drwxr-x--x 7 mysql mysql 4.0K Sep 12 21:39 .. -rw-r----- 1 mysql mysql 272M Sep 12 21:44 sbtest1.ibd $ sudo ls -alh /var/lib/mysql/sbtest total 141M drwxr-x--- 2 mysql mysql 25 Sep 12 21:44 . drwxr-x--x 7 mysql mysql 4.0K Sep 12 21:39 .. -rw-r----- 1 mysql mysql 140M Sep 12 21:44 sbtest1.ibd
  21. 断⽚化の解消 43 さっきとは違うDELETE⽂で50万⾏ 消しました。 mysql> SHOW TABLE STATUS ¥G ***************************

    1. row *************************** Name: sbtest1 Engine: InnoDB Version: 10 Row_format: Dynamic Rows: 491145 # 50万⾏ Avg_row_length: 457 Data_length: 224788480 Max_data_length: 0 Index_length: 16138240 Data_free: 37748736 # 37M
  22. 断⽚化の解消 44 $ sudo ls -alh /var/lib/mysql/sbtest total 273M drwxr-x---

    2 mysql mysql 25 Sep 12 21:41 . drwxr-x--x 7 mysql mysql 4.0K Sep 12 21:39 .. -rw-r----- 1 mysql mysql 272M Sep 12 21:44 sbtest1.ibd $ sudo ls -alh /var/lib/mysql/sbtest total 141M drwxr-x--- 2 mysql mysql 25 Sep 12 21:49 . drwxr-x--x 7 mysql mysql 4.0K Sep 12 21:46 .. -rw-r----- 1 mysql mysql 140M Sep 12 21:49 sbtest1.ibd
  23. DELETE⽅法の違い ・Data_free にカウントされる • Data_free にカウントされない 45 mysql> DELETE FROM

    sbtest1 WHERE id < 500000; mysql> SHOW TABLE STATUS ¥G <snip> Data_free: 116391936 # 116M mysql> DELETE FROM sbtest1 WHERE (id % 70 <= 35); mysql> SHOW TABLE STATUS ¥G Name: sbtest1 <snip> Data_free: 37748736 # 37M!?
  24. お知らせ • MySQL Casual Slack • https://mysql-casual- slackin.herokuapp.com • dbtech

    showcase 2019 • 9⽉25 〜 27 @ 秋葉原 • https://www.db-tech- showcase.com/dbts/tokyo 52