適切なインデックスを持ち、約 1.5 の推定サブツリー コストでクエリ プランに表示されるクエリがあります。プランはインデックス シークを示し、その後にキー ルックアップが続きます。これは、5 ~ 20 行のセットから 1 行を返すことが期待されるクエリには問題ありません (つまり、インデックス シークは 5 ~ 20 行を検索し、5 ~ 20 行を検索する必要があります)。キー ルックアップ、1 行を返す必要があります)。
対話的に実行すると、クエリはほとんどすぐに返されます。ただし、今朝の DB トレースは、ライブ (Web アプリ) からのランタイムが大きく異なることを示しています。通常、クエリは 100 未満の DB 読み取りを使用し、実質的にランタイムは 0 です... しかし、170,000 を超える DB 読み取りを消費し、最大 60 秒 (タイムアウト値よりも大きい) のランタイムを消費するいくつかの実行が得られます。
ディスク読み取りのこの変動を説明できるものは何ですか? クエリを対話的に比較し、高速実行と低速実行から取得したフィルター値を使用して 2 つの並列実行から実際の実行計画を使用しようとしましたが、対話的にこれらは使用される計画に実質的な違いを示しません。
また、このクエリをロックしている可能性のある他のクエリを特定しようとしましたが、それが DB 読み取りにそれほど影響を与えるかどうかはわかりません... いずれにせよ、このクエリは私のトレース ログで実行時に最悪になる傾向がありました。
更新:クエリが対話的に実行されたときに生成されるプランのサンプルを次に示します。
「インデックスがありません」というテキストは無視してください。現在のインデックスを変更することで、より少ないルックアップでより高速なクエリが可能になることは事実ですが、ここでは問題ではありません (適切なインデックスが既に存在します) 。これは実際の実行計画であり、実際の行数などの数値が表示されます。たとえば、インデックス シークでは、実際の行数は 16 で、I/O コストは 0.003 です。キー ルックアップの I/O コストは同じです。
更新 2:このクエリのトレースの結果は次のとおりです。
exec sp_executesql N'select [...column list removed...] from ApplicationStatus where ApplicationGUID = @ApplicationGUID and ApplicationStatusCode = @ApplicationStatusCode;',N'@ApplicationGUID uniqueidentifier,@ApplicationStatusCode bigint',@ApplicationGUID='ECEC33BC-3984-4DA4-A445-C43639BF7853',@ApplicationStatusCode=10
クエリは Gentle.Framework SqlBuilder クラスを使用して作成され、次のようにパラメーター化されたクエリが作成されます。
SqlBuilder sb = new SqlBuilder(StatementType.Select, typeof(ApplicationStatus));
sb.AddConstraint(Operator.Equals, "ApplicationGUID", guid);
sb.AddConstraint(Operator.Equals, "ApplicationStatusCode", 10);
SqlStatement stmt = sb.GetStatement(true);
IList apps = ObjectFactory.GetCollection(typeof(ApplicationStatus), stmt.Execute());