Transcript
Page 1: お金をかけないDBチューニング

お金をかけないDBチューニング

@boss_sato

Page 2: お金をかけないDBチューニング

DBサーバが重たい場合の対応

•サーバ側• 台数増やす、スペックアップ•DB側• レプリケーション ≒ 台数増やす• my.cnfチューニング•アプリ側• SQLチューニング

Page 3: お金をかけないDBチューニング

DBサーバが重たい場合の対応

•サーバ側• 台数増やす、スペックアップ•DB側• レプリケーション ≒ 台数増やす• my.cnfチューニング•アプリ側• SQLチューニング

Page 4: お金をかけないDBチューニング

DBサーバが重たい場合の対応

•サーバ側• 台数増やす、スペックアップ•DB側• レプリケーション ≒ 台数増やす• my.cnfチューニング•アプリ側• SQLチューニング

コストがかかる!監視対象が増える!重たいSQLが残ったまま!➡運用の手間がかかる サーバが重たい原因が残ったまま

Page 5: お金をかけないDBチューニング

DBサーバが重たい場合の対応

•サーバ側• 台数増やす、スペックアップ•DB側• レプリケーション ≒ 台数増やす• my.cnfチューニング•アプリ側• SQLチューニング

今回チューニングするのはこれ

Page 6: お金をかけないDBチューニング

my.cnfチューニング

Page 7: お金をかけないDBチューニング

my.cnfの設定方法

## 雛形ファイルがあるのでそれをコピーする$ pwd/usr/share/doc/MySQL-server-5.5.28$ ls -1 my-*my-huge.cnfmy-innodb-heavy-4G.cnfmy-large.cnfmy-medium.cnfmy-small.cnf$ cp my-huge.cnf /etc/my.cnf

Page 8: お金をかけないDBチューニング

my.cnfの雛形ファイルの種類

ファイル名 適したサーバ

my-small.cnf 64MB以下のメモリを搭載したサーバmy-medium.cnf 128MB以下のメモリを搭載したサーバmy-large.cnf 512MB以下のメモリを搭載したサーバ

my-huge.cnf 1GB~2GB以下のメモリを搭載したサーバ

my-innodb-heavy-4G.cnf

4GBのメモリとInnoDBで作成したDBで構築したサーバ

Page 9: お金をかけないDBチューニング

my.cnfのチューニング

•key_buffer_size• key_buffer_size = 256M• インデックスを保存するバッファサイズ• メモリの余裕がある場合は多く振る

my.cnfのチューニング ≒ メモリ割当の最適化 以下の点に留意しながら最適化を行う •サーバーのリソース •サーバー上で稼働しているミドルウェア

Page 10: お金をかけないDBチューニング

my.cnfのチューニング

•sort_buffer_size• sort_buffer_size = 2M• ソートを行う場合のバッファサイズ• ORDER | GROUP BYの実行速度があがる• record_buffer_size• record_buffer_size = 2M• インデックスを含まないクエリの実行速度があがる

Page 11: お金をかけないDBチューニング

my.cnfのチューニング

最適なメモリサイズの割り振り

key_buffer_size+(sort_buffer_size + record_buffer_size)× max_connections

実メモリサイズ + スワップメモリサイズ※MySQL以外のミドルウェアがある場合は そちらに振るメモリも考慮して割り振る

Page 12: お金をかけないDBチューニング

SQLチューニング

Page 13: お金をかけないDBチューニング

SQLの解析

•slow_queryを設置する## /etc/my.cnfに以下を記述[mysqld]long_query_time=1log-slow-queries=/var/log/slow_query.log

## 以下を記述するとインデックスを使用しないSQLも拾えるlog-queries-not-using-indexes

Page 14: お金をかけないDBチューニング

SQLの解析

•mysqlslowdumpコマンドで解析$ mysqldumpslow [option] [log_file]

## よく使うオプションは-s(並び替え)-s c → 総クエリ数の多い順-s l → 総ロックタイムの長い順-s r → 総行数の多い順-s t → 総実行時間の長い順-s a(l | r | c) → 各平均の長い順

Page 15: お金をかけないDBチューニング

## 文字列 → S、 数字 → N と置換してくれる## Count:総クエリ数 Time=平均実行時間(総実行時間)## Lock=平均ロックタイム(総ロックタイム) Rows=平均行数(総行数)

$ mysqldumpslow -s c slow_query.log | less

Count: 49 Time=1.49s (73s) Lock=0.00s (0s) Rows=1.0 (49), user[user]@2hosts SELECT * FROM tbl1 WHERE name = 'S' ORDER BY id LIMIT N

Count: 36 Time=1.47s (52s) Lock=0.00s (0s) Rows=1.0 (36), user[user]@2hosts SELECT * FROM tbl2 WHERE id = 'S' AND deleted = 'S' ORDER BY id LIMIT N . . .

Page 16: お金をかけないDBチューニング

重たいSQLの傾向

SELCT *FROM tbl1INNER JOIN tbl2 ON ...INNER JOIN tbl3 ON ...ORDER BY tbl1.created DESC, tbl2.created.DESCLIMIT 0, 20;

•複数テーブルをまたいだORDER BY

• ページングでよく使われるSQL• Using temporary; Using filesort がどうしても発生してしまう

Page 17: お金をかけないDBチューニング

重たいSQL対応その1

•SQLを分割する(ID取得)

• レコードをIDのみにする• レコードを減らすだけでもクエリ実行時間は結構減る

SELCT tbl1.idFROM tbl1INNER JOIN tbl2 ON ...INNER JOIN tbl3 On ...ORDER BY tbl1.created DESC, tbl2.created DESCLIMIT 0, 20;

Page 18: お金をかけないDBチューニング

重たいSQL対応その1

•SQLを分割する(表示データ取得)

• 取得したID毎に表示用のSQLを実行する• SQL本数は増えるが、IDをキーに取得しているので実行時間は0.1secとかで収まる

SELCT *FROM tbl1INNER JOIN tbl2 ON ...INNER JOIN tbl3 On ...WHERE tbl1.id = 1

Page 19: お金をかけないDBチューニング

重たいSQL対応その2

•無駄なJOIN、ORDER BYを減らす

• JOIN先のテーブルの件数次第では、JOINを減らすだけでXsec下げれたりする• ORDER BYも同様• ある程度の不整合に目をつぶるかも。。

SELCT tbl1.idFROM tbl1INNER JOIN tbl2 ON ...// INNER JOIN tbl3を削除ORDER BY tbl1.created DESCLIMIT 0, 20;

Page 20: お金をかけないDBチューニング

重たいSQLの対応まとめ

• 最低限のレコードを取得するようにする• なるべくJOINの数を減らす• テーブルをまたぐORDER BYはなるべく避ける

基本的な事をやるだけでも数sec落とす事は可能※10万件越えたあたりから効果は現れる?

Page 21: お金をかけないDBチューニング

それでもダメなら

Page 22: お金をかけないDBチューニング
Page 23: お金をかけないDBチューニング

おわり


Recommended