2009-08-25 9 views
0

SQL Server 2008.この非常に大きなクエリがあり、そのクエリには高いコストがかかります。ヒキガエルはそれでクエリチューニング機能を持っており、作られた唯一の変化は以下の通りであった:クエリの最適化。なぜTOADはこれをしたのですか?

前:

LEFT OUTER JOIN (SELECT RIN_EXT.rejected, 
           RIN_EXT.scar, 
           RIN.fcreceiver, 
           RIN.fcitemno 
          FROM RCINSP_EXT RIN_EXT 
           INNER JOIN dbo.rcinsp RIN 
            ON RIN_EXT.fkey_id = RIN.identity_column) RIN1 
     ON RCI.freceiver = RIN1.fcreceiver 
      AND RCI.fitemno = RIN1.fcitemno 
WHERE RED.[YEAR] = '2009' 

後:

LEFT OUTER JOIN (SELECT RIN_EXT.rejected, 
           RIN_EXT.scar, 
           RIN.fcreceiver, 
           RIN.fcitemno 
          FROM dbo.rcinsp RIN 
           INNER JOIN RCINSP_EXT RIN_EXT 
            ON RIN.identity_column = COALESCE (RIN_EXT.fkey_id , RIN_EXT.fkey_id)) RIN1 
     ON RCI.freceiver = RIN1.fcreceiver 
      AND RCI.fitemno >= RIN1.fcitemno -- ***** RIGHT HERE 
      AND RCI.fitemno <= RIN1.fcitemno 
WHERE RED.[YEAR] = '2009' 

フィールドのchar(3)フィールドであり、これはありますSQL Server 2008.

なぜ私のものよりもずっと速いのですか?

+0

気づいた場合は、FROM RINとINNER JOIN RIN_EXTから行いましたが、FRIN RIN_EXTとINNER JOIN RINから行っていました。あなたがコメントした1行を削除してメトリックスを実行したかどうか、そしてその特定の行がパフォーマンスを向上させているかどうかは分かりません。 – JustLoren

+0

ベストオプションは、2つのクエリのクエリプランを比較し、使用している演算子を確認することです。 –

+0

申し訳ありませんが、最初のスクリプトで残りの結合条件が欠落していました。 – DavidStein

答えて

2

"Before"クエリでON条件を表示していないため、TOADの変更内容がわかりません。しかし、私は何が起こったのかを推測します。

SQL Serverクエリオプティマイザは、コスト見積もりを使用してクエリプランを選択します。コスト見積もりは、行数の見積もりに基づいています。行数の見積もりが正確でない場合、オプティマイザは最適なプランを選択しない可能性があります。

一部の行数の見積もりは、統計がある列の書式(列=値)と同じように、通常は正確です。ただし、列数が外部キー制約によって関連付けられていない場合(column = othercolumn)、式が自明でない場合や複数の列が含まれる場合(expression = value)のように、行数の見積もりを推測できるものがあります。

統計が行数の見積もりをガイドしない場合、SQL Serverは一般的な見積もりを使用します。見積もり計画の行数見積もりと実際の計画の実際の見積もり額を比較すると、問題が発生し、オプティマイザがその行数見積もりを変更することを「トリック」することがあります。

結果を実際に制限しないANDで述語を追加すると、オプティマイザが余分であると認識できない場合は、行数の見積もりを低くすることができます。同様に、結果が実際には得られないORで述部を追加する場合は、行数の見積もりを増やすことができます。

おそらくここでは、行数の見積もりが高すぎます。余分な述語がそれらを修正しているため、計画のコスト見積もりが向上し、最終的には計画の選択肢が改善されます。

2

昇順索引の検索引数のように見えます - それは> = - 追加されて以来、残りの部分については十分にはわかりませんが、明らかにRCI.fitemnoに関する推測できるデータがあります残りのクエリ

それはこのことを奇妙だ:

 AND RCI.fitemno >= RIN1.fcitemno -- ***** RIGHT HERE 
     AND RCI.fitemno <= RIN1.fcitemno 

は、このになっていませんでした:彼らは同等なので

 AND RCI.fitemno = RIN1.fcitemno 

2

クエリよりも大きいか小さいクエリを追加することは、クエリオプティマイザがその列のインデックスを使用するように時々微妙に変化する古い技です。だから、このトリック:

AND RCI.fitemno >= RIN1.fcitemno 
AND RCI.fitemno <= RIN1.fcitemno 

が存在する場合RIN1とRCI fitemno列に索引を使用するようにデータベースを強制します。私はあなたがこれを行うときに、一時的なインデックスが即座に作成されるかどうかはわかりません。

私はこれまで、DB2データベースを使ってこれらのやり方をしていましたが、うまく機能しました。

関連する問題