2

次のテーブルとSQLがあります。

T1:ID、col2、col3-PK(ID)-23mil行

T2:ID、col2、col3-PK(ID)-23mil行

T3:ID、名前、値-PK(ID、name)-66mil行

1)以下のSQLは、10k行の結果セットを非常に高速に返します。問題はありません。

select top 10000 T1.col2, T2.col2, T3.name, T4.value 
from T1, T2, T3  
where T1.ID = T2.ID and T1.ID *= T3.ID and T3.name in ('ABC','XYZ') 
and T2.col1 = 'SOMEVALUE'

2)以下のSQLはFOREVERを取りました。

select top 10000 T1.col2, T2.col2, 

ABC  = min(case when T3.name='ABC ' then T3.value end)  
XYZ  = min(case when T3.name='XYZ ' then T3.value end)  

from T1, T2, T3  

where T1.ID = T2.ID and T1.ID *= T3.ID and T3.name in ('ABC','XYZ')
and T2.col1 = 'SOMEVALUE'

group by T1.col2, T2.col2, 

これら2つのクエリ間のショープランの唯一の違いは、クエリ2)の以下です。私はそれを100%理解していません、それは一時テーブルにトップ10000のない全体の結果セットを選択し、それでグループ化を行うのですか?だから遅いの?

STEP 1
    The type of query is SELECT (into Worktable1).
    GROUP BY
    Evaluate Grouped MINIMUM AGGREGATE.

    FROM TABLE ...etc..

    TO TABLE
        Worktable1.

STEP 2
    The type of query is SELECT.

    FROM TABLE
        Worktable1.
    Nested iteration.
    Table Scan.
    Forward scan.
    Positioning at start of table.
    Using I/O Size 16 Kbytes for data pages.
    With MRU Buffer Replacement Strategy for data pages.

私の質問は

1)クエリがなぜ遅いのか2)とても遅い

2)クエリロジックを同じに保ちながら修正するにはどうすればよいですか。できれば、以前と同じように1つのSQLを選択するように制限してください。

ありがとうございました

4

1 に答える 1

1

一般的な答えかもしれませんが、グループ化する列にインデックスを付けると思います。

編集/改訂:問題を再検討した後の私の理論は次のとおりです。クエリのSELECTステートメントは、常に最後に実行される行です。以下に指定されたデータセットから必要な値を取得するステートメントであるため、これは理にかなっています。クエリでは、データセット全体(数百万のレコード)が、指定したMIN値式に対して評価されます。selectステートメントで2つのMIN列を指定したため、データセット全体で2つの別個の関数が呼び出されます。 データセットがフィルタリングされ、MIN列が決定された後、上位10000行が選択されます。

一言で言えば、あなたは何百万ものレコードに対して2つの数学関数を実行しています。これには、特にインデックスがない場合、かなりの時間がかかります。

解決策は、派生テーブルを使用することです。以下のコードはコンパイルしていませんが、使用するコードに近いものです。データセット全体ではなく、10,000レコードの最小値のみを取得します。

つまり

    Select my_derived_table.t1col2, my_derived_table.t2col2,
    ABC  = min(case when my_derived_table.t3name ='ABC ' then my_derived_table.t3value end),  
    XYZ  = min(case when my_derived_table.t3name='XYZ ' then my_derived_table.t3value end)
    FROM
      (Select top 10000 T1.col2 as t1col2, 
              T2.col2 as t2col2, 
              t3.name as t3name, 
              t3.value as t3.value
       from T1, T2, T3
       where T1.ID = T2.ID 
         and T1.ID *= T3.ID 
         and T3.name in ('ABC','XYZ')
         and T2.col1 = 'SOMEVALUE') my_derived_table
group by my_derived_table.t1col2, my_derived_table.t2col2
于 2011-04-01T20:29:23.857 に答える