sql >> データベース >  >> RDS >> Sqlserver

パラメータを指定して DISTINCT を使用すると、select ステートメントのパフォーマンスが低下する

    問題は、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 がないからです。見落としだったと思います。



    1. SQLServerでのデータファイル管理の基本

    2. パターンに一致する値を含むオブジェクトのJSON配列を検索します

    3. LinuxにSQL*PLUSクライアントをインストールする方法

    4. MySqlDBテーブルへのデータフレームの書き込み