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

MySQLの容量とか圧縮まわり

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

 MySQLの容量とか圧縮まわり

Avatar for Satoshi MITANI

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