何もしてないのに突然クエリが遅くなった時の対処方法
はじめに
アイスタイルDBREのsuzukitoです。
数年ぶりに「なんにもしてないのに突然クエリが遅くなる現象」に遭遇したので、いつもやっている対処方法をまとめてみました。
こんなことがあります
何もしてないのにクエリが突然遅くなった!
DBサーバーのCPU使用率が100%になって、クエリが滞留しまくっているぞ!
ちゃんとインデックスも作ってあるから、今日の午前中まで何も問題が起きてなかったのに。
最近リリースもしてないし、本当に何もしてない。
どうしたらいいんだろう。
まずはこれをお試し下さい
統計情報の更新をやってみましょう。
インデックスを使用しない実行計画が生成されている可能性が高いです。
遅くなったクエリが特定できている場合は、EXPLAINで実行計画を確認すると良いです。統計情報更新効果の有無がはっきりします。
統計情報の更新方法
MySQL
クエリが特定できて、テーブル名が分かっている場合
ANALYZE TABLE tbl_name
テーブル名が分からない場合
ANALYZE TABLE文を生成するクエリを実行して、生成されたクエリを実行します。
SELECT
CONCAT('ANALYZE TABLE ', table_name, ';') AS stmt
FROM
information_schema.tables
WHERE
table_schema = DATABASE()
AND table_type = 'BASE TABLE'
上記クエリを実行すると次の様な結果が出力されるので、コピーして実行します。
+-------------------------------------------+
| stmt |
+-------------------------------------------+
| ANALYZE TABLE actor; |
| ANALYZE TABLE actor_info; |
| ANALYZE TABLE address; |
| ANALYZE TABLE category; |
~中略~
| ANALYZE TABLE city; |
| ANALYZE TABLE staff; |
| ANALYZE TABLE staff_list; |
| ANALYZE TABLE store; |
+-------------------------------------------+
SQL Server
クエリが特定できて、テーブル名が分かっている場合
UPDATE STATISTICS table_or_indexed_view_name
テーブル名が分からない場合
全テーブルの統計情報を更新するストアドプロシージャを実行します。
EXEC sp_updatestats
PostgreSQL
クエリが特定できて、テーブル名が分かっている場合
ANALYZE table_and_columns
テーブル名が分からない場合
テーブル名を省略すると、全テーブルを対象にします。
ANALYZE
これでダメだったらどうしたらいいの?
おそらくデータ量が増えて、本当にクエリが遅くなったんだと思われます。
遅いクエリを特定して実行計画を確認し、クエリに対応するインデックスを作成しましょう。
作成済みのインデックスが検索列だけを指定している場合は、カバリングインデックスの作成を検討してみて下さい。
なんでこうなるの?
なんででしょうね?
発生したときは障害になっているため、すぐに対処する必要があり、原因調査までしていません。数百台のDBサーバーを管理していますが、数年に一回程度の頻度で経験しています。
統計情報はRDBMSがクエリの実行計画を生成する際に参照する情報です。
ほとんどのRDBMSでは、テーブル行の一定以上の割合が更新されると自動的に更新されるようになっています。
また、テーブルの行数が多くなると、実行計画の自動更新が行われるような割合の更新が発生しにくくなるので、バッチで定期的に統計情報を更新させる運用をする場合もあります。
テーブル内のデータの分布が分からないと適切な実行計画が生成できないので、統計情報の更新は基本的に正しい行為だと思います。
が、ごくまれに、統計情報の更新が原因で実行計画が都合の悪い方に変わる事があります。
そんな、まれな状況に遭遇したら、まずは統計情報を手動で更新してみることをオススメします!
Discussion