問題は、DISTINCT がパラメーターでパフォーマンスの低下を引き起こしていることではなく、オプティマイザーが [email protected] _ADMINISTRATOR は 1=1 と同じです。 なしで結合を最適化することはありません 結合の結果に基づいて重複を返す必要があるためです。
なんで? @IS_ADMINISTRATOR =1 以外の値の場合、すべての結合を破棄する実行計画は無効になるためです。計画をキャッシュしているかどうかに関係なく、その計画は生成されません。
これは、私の 2008 サーバーでのパラメーター化されていないクエリと同様に機能します:
-- PARAMETRIZED QUERY declare @IS_ADMINISTRATOR int declare @User_ID int set @IS_ADMINISTRATOR = 1 -- 1 for administrator 0 for normal set @User_ID = 50 IF 1 = @IS_ADMINISTRATOR BEGIN SELECT DISTINCT -- PLEASE REMEMBER DISTINCT MAKES THE DIFFERENCE!!! DOC.DOCUMENT_ID FROM DOCUMENTS DOC LEFT OUTER JOIN FOLDERS FOL ON FOL.FOLDER_ID = DOC.FOLDER_ID LEFT OUTER JOIN ROLES ROL ON (FOL.FOLDER_ID = ROL.FOLDER_ID) WHERE 1 = 1 END ELSE BEGIN SELECT DISTINCT -- PLEASE REMEMBER DISTINCT MAKES THE DIFFERENCE!!! DOC.DOCUMENT_ID FROM DOCUMENTS DOC LEFT OUTER JOIN FOLDERS FOL ON FOL.FOLDER_ID = DOC.FOLDER_ID LEFT OUTER JOIN ROLES ROL ON (FOL.FOLDER_ID = ROL.FOLDER_ID) WHERE ROL.USER_ID = @USER_ID END
プレ>あなたの例を実行しているクエリプランから明らかなのは、
@IS_ADMINISTRATOR = 1
です1=1
と同じように最適化されません .パラメータ化されていない例では、JOINS は完全に最適化されており、DOCUMENTS テーブル内のすべての ID を返すだけです (非常に単純です)。
@IS_ADMINISTRATOR <> 1
の場合、さまざまな最適化が欠落しています .たとえば、LEFT OUTER JOIN
S は自動的にINNER JOIN
に変更されます なし そのOR
節ですが、 そのまま残されます それまたは句。この回答も参照してください。> 動的 SQL の代替手段として。
もちろん、これは元の質問のパフォーマンスの違いを実際には説明していません。そこに OR がないからです。見落としだったと思います。