はじめに
先日、業務で「このSQL文の実行計画取っといてください」と指示を受けたのですが、
そのときの自分は「そもそも実行計画ってなに??」という状態でした。
この記事では、そんな状態の自分が、なんとか指示をこなすために調べたことを整理して共有してみようと思います。
そもそも実行計画とは?
・クエリの先頭にEXPLAINを文頭につけると、実行計画というものが取得できるらしい
・実行計画というのは、「クエリがどの手順でデータを取得するかを示す計画書」のようなもの
・具体的に分かるのは以下のような情報
テーブルのスキャンにインデックスを使っているかどうか
命令の開始コスト(スキャン対象の行数に関わらずかかるコスト)
命令の終了コスト(スキャン対象行数が増えると増えるコスト)
推定行数(スキャン対象となる行数)
3つの基本コマンド-EXPLAIN,ANALYZE,VACUUM-
実行計画に関わるSQLコマンドとしては、主にこの3つが挙げられます。
EXPLAINコマンド
クエリの先頭につけると、実行計画を取得できる。
取得された実行計画は、統計情報をもとに算出した推定値であることに注意。
※統計情報についてはANALYZEの説明を参照
(例)
EXPLAIN
SELECT *
FROM hoge_table;
(出力例)
Seq Scan on hoge_table (cost=0.00..10.24 rows=224 width=153)
※Seq Scanは「インデックス使って検索してないよ~」という意味。
※cost=0.00..10.24は、推定開始コストが0.00、推定終了コストが10.24という意味。
ANALYZEコマンド
統計情報を更新するコマンド。
EXPAINによって取得される実行計画は、推定値を出すにあたり、この統計情報を参照する。
※EXPAINコマンドを実行しても、統計情報の更新は行われない。
統計情報が古いと正しい推定値の実行計画が取得できないため、
EXPLAINを行う前に必ずANALYZEを実行しておくと安心。
だが、後述のVACUUMと一緒に行うと、もっと安心。
VACUUMコマンド
DELETE文でレコードを物理削除したり、UPDATE文でレコードを更新したりしても、実は削除前/更新前のレコードは、物理的にディスクの中に残っている。
この残ったデータをクリーンアップするのがVACUUMコマンド。
特に大規模なデータ削除を行った場合、VACUUMをしないと、テーブルの行数に対してクエリのパフォーマンスが下がることがある。
2つの応用コマンド-EXPLAIN ANALYZE,VACUUM ANALYZE-
EXPLAIN ANALYZEコマンド
EXPLAINコマンド単体では推定値しか出ないが、
EXPLAIN ANALYZEを実行すると実測値も出せる。
ややこしいが、ANALYZEが入っているからといって、統計情報が更新されるわけではないので注意。
VACUUM ANALYZEコマンド
こちらはその名の通り、
VACUUMとANALYZEを一緒に実行してくれるコマンド。
実行計画を取得するクエリについて、そのクエリが関連するテーブル全て
(FROM句で直接指定しているテーブルやJOINで結合しているテーブルなど)
に。VACUUM ANALYZEをかけてから実行計画を取得すると確実。
結局どうすればいいの??
VACUUM ANALYZE → EXPLAIN ANALYZEの順で実行しておければ、とりあえず間違いないと思います。
(例)
-- 関連するテーブルをVACUUM ANALYZE
VACUUM ANALYZE tableA, tableB, tableC;
-- 実行計画を取得(推定値・実測値)
EXPLAIN ANALYZE
[テーブルA,B,Cを結合して値を取得するクエリ]
取得できたらどう使うの?
色々条件を変えてみて問題ないか(クエリのパフォーマンスが明らかに遅くなっていないかどうかなど)を見ます。
例えば、
・テーブルに登録されている件数を10件→100件→1000件と増やしてみる
・クエリに渡すパラメータの数を増やしてみる
など。
分かりやすい指標としては、以下の項目が極端に変化していたらクエリの見直しが必要です。
Planning time(最適な実行計画を作るためにかかる時間)
Execution time(実際にクエリを実行し、データを取得・処理するのに要した時間)
おわりに
実行計画を取得する分には、とりあえずこの記事に書いてある知識で問題ないはずです。
実行計画の読み方については、長くなるので今回は触れないでおきます。
というか自分も細かいところまでまだ勉強できていません...。