クエリのパフォーマンスが低下している場合のトラブルシューティング : 基数推定
SQL Server のクエリ オプティマイザはコストを基に最適化を行います。つまり、実行のための推定処理コストが最も低いクエリ プランが選択されます。クエリ プランを実行する際のコストは、主に次の 2 つの要素に基づいて決定されます。
クエリ プランの各レベルで処理される行の総数。これをプランのカーディナリティと呼びます。
クエリ内の演算子で指示されているアルゴリズムのコスト モデル。
最初の要素であるカーディナリティは、2 番目の要素であるコスト モデルの入力パラメータとして使用します。そのため、カーディナリティが向上すると、推定コストが適切になり、その結果実行プランも高速化します。
カーディナリティの推定には、インデックスまたは統計を作成するときに手動か自動で作成されたヒストグラムが主に使用されます。また、クエリの制約情報および論理再書き込みが使用されることもあります。
次の例では、カーディナリティを正確に計算することができません。その場合コストが正しく計算されないので、最適なクエリ プランが選択されない場合があります。次に示す構造をクエリで使用しないようにすることで、クエリのパフォーマンスが向上する場合があります。別のクエリ式や他の方法で代替できることがあるので、それについても記載してあります。
同一テーブルの異なる列どうしを比較する比較演算子を述語で使用しているクエリ。
次のいずれかの条件に該当し、演算子を述語で使用しているクエリ。
演算子の一方の側で使用されている列の統計が存在しない。
統計内の値の分布が不均一であるにもかかわらず、クエリにより選択度の高い値セットがシークされる。これに該当するのは、主に演算子が等号 (=) 以外である場合です。
等しくない (!=) 比較演算子または NOT 論理演算子を述語で使用している。
SQL Server の組み込み関数、または引数が定数値でないスカラ値関数かユーザー定義関数を使用するクエリ。
算術連結演算子または文字列連結演算子によって結合した列を含んでいるクエリ。
クエリのコンパイル時または最適化時に値が確定しない変数を比較するクエリ。
上記に該当するクエリのパフォーマンスを向上させるためには、次の方法を使用できます。
クエリで使用している列に有用なインデックスまたは統計を作成します。詳細については、「インデックスの設計」および「クエリのパフォーマンスを向上させるための統計の使用」を参照してください。
比較演算子または算術演算子を使用して複数の列を比較または結合している場合、計算列を使用してクエリを書き換えることを検討します。たとえば、次のクエリでは 2 つの列の値を比較しています。
SELECT * FROM MyTable WHERE MyTable.Col1 > MyTable.Col2
Col1 と Col2 の差 (Col1 - Col2) を計算する計算列 Col3 を MyTable に追加すると、パフォーマンスが向上する場合があります。クエリは次のように書き換えることができます。
SELECT * FROM MyTable WHERE Col3 > 0
MyTable.Col3 にインデックスを作成すると、パフォーマンスがさらに向上する場合があります。