チューニングしたクエリがインデックスを使うようになると、複合インデックスを定義することを考えなくなってしまうことがあります。 しかし、オプティマイザがそのインデックスを使うのは、クエリに対する「適切な」インデックスだからというより、フルテーブルスキャンよりも 効率がいいからという方が正しいと言えます。つまりそれは、最適化されたインデックスだとは言い難いでしょう。
前の例では、実行計画において間違った列の順番を認識する難しさを表しました。多くの場合、述語情報はうまく隠されてしまっており、 インデックスの使用法が最適化されているかどうかを確認するのに、述語情報を調べなくてはなりません。
例として、SQL Server Management Studioでは図にあるように、インデックスの処理単位にマウスカーソルを載せた(hoverした)時にだけ、
ツールチップとして述語情報が表示されます。この実行計画では、
SCALE_SLOW
インデックスが使われており、ID2
に
対する条件がフィルタ述語であると表示されています(「Seek Predicades」ではなく「Predicate」の方)。
MySQLやPostgreSQLの実行計画から述語情報を 取り出すのは、さらに厄介です。付録Aでさらに詳しく説明しています。
実行計画の中で述語情報がどんなに小さく表示されていたとしても、それがパフォーマンスに大きな影響を与えるのは間違いありません。 システムが成長していく時はなおさらです。成長していくのはデータ量だけではなく、アクセス量も増えていくことをもう一度考えてみましょう。アクセス量は、 スケーラビリティの関数のもう1つのパラメータであると言えます。
協力してください
この記事が気に入ったら、私の書いた本「SQLパフォーマンス詳解」や私によるトレーニングもきっと気にいるはず。
図3.4では、 データ量を一定とした場合の、アクセス量に応じた応答時間を表しています。前の例と同じクエリで、常に最もデータ量の大きい セクションを指定した場合の実行時間です。つまり、図3.2の最後の点と同じです。
図3.4システム負荷に対するスケーラビリティ

点線は、SCALE_SLOW
インデックスを使った時の
応答時間です。同時に25クエリが動いている時は、32秒までグラフが伸びています。全く負荷がない、つまり開発環境と同じような状態と比べて、
30倍の時間がかかっていることになります。開発環境に本番環境の完全なコピーデータがあるとしても、バックグラウンドの負荷は、本番環境における
クエリの実行速度を遅くする原因になり得るのです。
実線は、フィルタ述語を一切持たないSCALE_FAST
インデックスを使った時の応答時間を表しています。こちらは、25クエリが同時に動いている時でも、応答時間は2秒以下を保っています。
注記
注意深い実行計画の調査結果は、 うわべだけのベンチマークよりも信用のおけるものです。
完全な負荷テストは意味のあることですが、そのための手間はかかります。
問題になる可能性のある応答時間は、開発中は軽視されていることがよくあります。これは、我々が「本番のより強力なハードウェア」が あるのだからもっと良いパフォーマンスが出るはずと思い込んでしまうことに原因があります。どちらかと言えば、本番環境の方がより複雑な構成になるため、 開発環境では起こり得なかったレイテンシの蓄積によって、逆の結果になることも 多いようです。本番環境と同等のインフラでテストした時でも、バックグラウンドの負荷が応答時間の違いの原因になってしまうこともあります。次の節では、 「より強力なハードウェア」により高速なレスポンスを期待するのが間違いであるという話を取り上げます。
関連情報
複雑な環境におけるレイテンシについての記事”レイテンシ: セキュリティ vs. パフォーマンス”
Jams Golick氏による記事 “負荷が 高すぎるからサーバを増やそう”