主キー(autoinc bigint)を持つ35の列と、クラスター化されていない、一意でない3つのインデックス(それぞれが1つのint列にある)を持つ支払いのテーブルがあるとします。
テーブルの列には、2つの日時フィールドがあります。
支払期日
datetime NOT NULL
編集日
datetime NULL
テーブルには約120万行があります。edit_date column=nullを持つ行は約1000行のみです。9000行のedit_dateがnullでなく、payment_dateと等しくない他の行にはedit_date=payment_dateがあります
次のクエリを実行すると1:
select top 1 *
from payments
where edit_date is not null and (payment_date=edit_date or payment_date<>edit_date)
order by payment_date desc
サーバーはそれを行うのに数秒かかります。しかし、クエリ2を実行すると:
select top 1 *
from payments
where edit_date is not null
order by payment_date desc
実行は、データベース'tempdb'のログファイルがいっぱいになります。データベースのトランザクションログをバックアップして、ログスペースを解放します。
*を特定の列に置き換える場合は、クエリ3を参照してください。
select top 1 payment_date
from payments
where edit_date is not null
order by payment_date desc
また、数秒で終了します。
魔法はどこにありますか?
編集 クエリ1を変更して、2番目のクエリとまったく同じ行数で動作するようにしました。それでも、クエリ2がtempdbを埋めている間、1秒で戻ります。
答え 私はインデックスを追加するためのアドバイスに従い、両方の日付フィールドに対してこれを行いました-すべてが期待どおりに迅速に機能し始めました。ただし、問題は、この正確な状況でSQLサーバーが同様のクエリ(クエリ1とクエリ2)で異なる動作をする理由です。サーバー最適化のロジックを理解したかったのです。両方のクエリが同様にtempdbを使用した場合は同意しますが、使用しませんでした。
結局、私は最初の答えとしてマークを付けます。そこでは、私の問題の必須の症状が見られ、これを回避する方法についての最初の考えもあります(つまり、不注意)。