lt・dbチューニング
TRANSCRIPT
![Page 1: Lt・dbチューニング](https://reader034.vdocuments.pub/reader034/viewer/2022051706/58efc9541a28ab04448b45e7/html5/thumbnails/1.jpg)
DBチューニング~MySQL編~
by poll seed
![Page 2: Lt・dbチューニング](https://reader034.vdocuments.pub/reader034/viewer/2022051706/58efc9541a28ab04448b45e7/html5/thumbnails/2.jpg)
まずは、テーブルを作る
商品テーブル
都道府県
商品
分類
![Page 3: Lt・dbチューニング](https://reader034.vdocuments.pub/reader034/viewer/2022051706/58efc9541a28ab04448b45e7/html5/thumbnails/3.jpg)
インデックスなし1. 商品全体テーブルを作成
CREATE TABLE `item` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `pref_code` int(11) NOT NULL, `items_code` int(11) NOT NULL, `classify_code` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8
2. 各々のcodeに対して正規化しテーブルを生成→比較のためキーなどは設けない
![Page 4: Lt・dbチューニング](https://reader034.vdocuments.pub/reader034/viewer/2022051706/58efc9541a28ab04448b45e7/html5/thumbnails/4.jpg)
クエリの実行計画1. Explainにより実行計画を調べる
explain SELECT * FROM item i inner join pref p on i.pref_code = p.pref_code WHERE p.pref_code = 1 ;
2. 実行計画結果
# id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra 1, SIMPLE, p, const, PRIMARY, PRIMARY, 4, const, 1, 1, SIMPLE, i, ALL, , , , , 21, Using where
※「i」テーブルのtypeが「ALL」となっている
![Page 5: Lt・dbチューニング](https://reader034.vdocuments.pub/reader034/viewer/2022051706/58efc9541a28ab04448b45e7/html5/thumbnails/5.jpg)
ALLとはそもそもtypeとはなんだろうか
結論から言えば、「結合型」
さらに言えば、ALLと言うのは「フルテーブルスキャン」のALLである。ただの爆遅結合ということ
要は、ALLなんて出してはいけない
![Page 6: Lt・dbチューニング](https://reader034.vdocuments.pub/reader034/viewer/2022051706/58efc9541a28ab04448b45e7/html5/thumbnails/6.jpg)
改善しよう
typeで爆速なのがsystem, constである。
systemというのは1レコードのみなので「const」,
次に早い「eq_ref」を目指すというのがエンジニアの必須事項
![Page 7: Lt・dbチューニング](https://reader034.vdocuments.pub/reader034/viewer/2022051706/58efc9541a28ab04448b45e7/html5/thumbnails/7.jpg)
手を加える11. indexの追加
ALTER TABLE `test`.`item` ADD INDEX `idx_item1` USING BTREE (`pref_code` ASC);
2. 実行計画
# id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra 1, SIMPLE, p, const, PRIMARY, PRIMARY, 4, const, 1, 1, SIMPLE, i, ALL, idx_item1, , , , 21, Using where
※idx_item1がキーの候補として出てきた。ただし、まだALLである。
![Page 8: Lt・dbチューニング](https://reader034.vdocuments.pub/reader034/viewer/2022051706/58efc9541a28ab04448b45e7/html5/thumbnails/8.jpg)
pref_codeにインデックスをつけることについて考える1
通常、B木インデックスをつける時は、カーディナリティの高い列を選ぶことが前提としてある
なぜならば、B木をより平坦にする必要があるからである。平坦というのはリーフが多い状態
具体的にはレコード全体の5%以下に抑えることができる場合、インデックスを張るのは有効と言われる
![Page 9: Lt・dbチューニング](https://reader034.vdocuments.pub/reader034/viewer/2022051706/58efc9541a28ab04448b45e7/html5/thumbnails/9.jpg)
pref_codeにインデックスをつけることについて考える2
pref_codeというのは都道府県である。よって、47
件のデータが存在する。1件につき全体のデータを大体2.1%程度に絞る事が可能
先の前提を元にすれば充分インデックスを張るのが有効だと言えよう
![Page 10: Lt・dbチューニング](https://reader034.vdocuments.pub/reader034/viewer/2022051706/58efc9541a28ab04448b45e7/html5/thumbnails/10.jpg)
手を加える21. 外部キーを付ける
ALTER TABLE `test`.`item` ADD CONSTRAINT `fk_item1` FOREIGN KEY (`pref_code`) REFERENCES `test`.`pref` (`pref_code`) ON DELETE NO ACTION ON UPDATE NO ACTION;
2. 実行計画
# id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra 1, SIMPLE, p, const, PRIMARY, PRIMARY, 4, const, 1, 1, SIMPLE, i, ALL, idx_item1, , , , 21, Using where
![Page 11: Lt・dbチューニング](https://reader034.vdocuments.pub/reader034/viewer/2022051706/58efc9541a28ab04448b45e7/html5/thumbnails/11.jpg)
変わっていない?
![Page 12: Lt・dbチューニング](https://reader034.vdocuments.pub/reader034/viewer/2022051706/58efc9541a28ab04448b45e7/html5/thumbnails/12.jpg)
もう一度先ほどの話を見てみよう
![Page 13: Lt・dbチューニング](https://reader034.vdocuments.pub/reader034/viewer/2022051706/58efc9541a28ab04448b45e7/html5/thumbnails/13.jpg)
pref_codeにインデックスをつけることについて考える1
通常、B木インデックスをつける時は、カーディナリティの高い列を選ぶことが前提としてある
なぜならば、B木をより平坦にする必要があるからである。平坦というのはリーフが多い状態
具体的にはレコード全体の5%以下に抑えることができる場合、インデックスを張るのは有効と言われる
![Page 14: Lt・dbチューニング](https://reader034.vdocuments.pub/reader034/viewer/2022051706/58efc9541a28ab04448b45e7/html5/thumbnails/14.jpg)
どういうことか
言うなれば、概算としてレコードを2.1%におさえれるという想定で先のインデックスを張り、外部キーまで加えたのにALLのまま
現場では得てしてこういうことが起こる。
それでは、このカラクリを紐解いてみよう。
![Page 15: Lt・dbチューニング](https://reader034.vdocuments.pub/reader034/viewer/2022051706/58efc9541a28ab04448b45e7/html5/thumbnails/15.jpg)
件数ベースで確認1. 件数を見てみよう
SELECT COUNT(*), COUNT(IF(pref_code = 1, 1, NULL)) FROM test.item;
2. 件数の結果
# count(*), count(if(pref_code=1,1,null)) 21, 16
※全体の76%以上がpref_code=1となっている。
想定では高いと思っていたが、データ的にはカーディナリティが低いのである。
![Page 16: Lt・dbチューニング](https://reader034.vdocuments.pub/reader034/viewer/2022051706/58efc9541a28ab04448b45e7/html5/thumbnails/16.jpg)
データ確認1select * from item where pref_code <> 1;
# id, pref_code, items_code, classify_code 1, 3, 1, 1 18, 2, 1, 1 19, 2, 2, 1 20, 2, 3, 1 21, 2, 4, 1
※3のカーディナリティは4.7%と高いため、こいつで条件を見てみる
![Page 17: Lt・dbチューニング](https://reader034.vdocuments.pub/reader034/viewer/2022051706/58efc9541a28ab04448b45e7/html5/thumbnails/17.jpg)
データ確認2
1. 実行計画をpref_code=3で見てみる
explain SELECT * FROM item i inner join pref p on i.pref_code = p.pref_code where p.pref_code = 3;
2. 結果
# id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra 1, SIMPLE, p, const, PRIMARY, PRIMARY, 4, const, 1, 1, SIMPLE, i, ref, idx_item1, idx_item1, 4, const, 1,
※問題なくインデックスが使われている
![Page 18: Lt・dbチューニング](https://reader034.vdocuments.pub/reader034/viewer/2022051706/58efc9541a28ab04448b45e7/html5/thumbnails/18.jpg)
まとめB木インデックスをつける時は、カーディナリティの高い列を選ぶ
レコード全体の5%以下に抑えることができる場合、インデックスを張るのは有効
ただし、データ件数によっては、インデックスが有効でない場合も実際の現場では多い
![Page 19: Lt・dbチューニング](https://reader034.vdocuments.pub/reader034/viewer/2022051706/58efc9541a28ab04448b45e7/html5/thumbnails/19.jpg)
発展として複合インデックスについてはどうか?
カーディナリティの高い順に貼っていくのが妥当と思われる
現場でデータ件数を元に決めるのがよい
検索するときも、インデックスが効くようにWhere文で検索する順序に注意
![Page 20: Lt・dbチューニング](https://reader034.vdocuments.pub/reader034/viewer/2022051706/58efc9541a28ab04448b45e7/html5/thumbnails/20.jpg)
余力があればハンズオン
以下のURLにアクセス
https://raw.githubusercontent.com/pollseed/linux_setup/master/src/hackathon/db/tuning_before.sql
Q1~Q3をできるところまで
![Page 21: Lt・dbチューニング](https://reader034.vdocuments.pub/reader034/viewer/2022051706/58efc9541a28ab04448b45e7/html5/thumbnails/21.jpg)
資料
以下のドキュメントも参考にして下さい
https://raw.githubusercontent.com/pollseed/linux_setup/master/src/hackathon/db/doc.md
![Page 22: Lt・dbチューニング](https://reader034.vdocuments.pub/reader034/viewer/2022051706/58efc9541a28ab04448b45e7/html5/thumbnails/22.jpg)
Fin