2012-02-13 12 views
1

を登録しよう私は30分以上実行し、非常に単純なクエリに関するパフォーマンスの問題を持っている:集約は、パフォーマンスの問題(SQLサーバー)

SELECT P.pID 
    ,COUNT(T1.ID) AS NB1 
    ,COUNT(T2.ID) AS NB2 
    ,COUNT(T3.ID) AS NB3 
    ,COUNT(T4.ID) AS NB4 
    ,COUNT(T5.ID) AS NB5 

FROM MainTable P 

LEFT OUTER JOIN Table1 T1 ON P.pID = T1.pID 
LEFT OUTER JOIN Table2 T2 ON P.pID = T2.pID 
LEFT OUTER JOIN Table3 T3 ON P.pID = T3.pID 
LEFT OUTER JOIN Table4 T4 ON P.pID = T4.pID 
LEFT OUTER JOIN Table5 T5 ON P.pID = T5.pID 

GROUP BY P.pID 

各クエリは、数ミリ秒で答えると同じように:

ex。 例:

SELECT P.pID 
     ,COUNT(T1.ID) AS NB1 

    FROM MainTable P 
    LEFT OUTER JOIN Table1 T1 ON P.pID = T1.pID 

    GROUP BY P.pID 

私は数ミリ秒で任意のアグリゲーション(COUNTまたは他の何か)クエリの実行を使用しない場合

。 SELECT P.pID

明らかにすべてのインデックスが設定されているなど
FROM MainTable P 

LEFT OUTER JOIN Table1 T1 ON P.pID = T1.pID 
LEFT OUTER JOIN Table2 T2 ON P.pID = T2.pID 
LEFT OUTER JOIN Table3 T3 ON P.pID = T3.pID 
LEFT OUTER JOIN Table4 T4 ON P.pID = T4.pID 
LEFT OUTER JOIN Table5 T5 ON P.pID = T5.pID 

GROUP BY P.pID 

... のみ「減速」要素は、このPIDはVARCHAR(50)ですが、私はそれを変更することはできませんし、私の意見ではということですここでの主な問題ではありません。

私は正常に動作するすべてのユニオンを含む回避策を使用しましたが、私は本当になぜこれが長すぎるのだろうと思っています、これを複数の左の結合に集約する方法は本当にレポートプロジェクトの共通のものです。

ご協力いただきありがとうございます。

[編集] thxからARION私は素敵な仕事をしています。

しかし、私の主な関心事は、複数の左結合でクエリを記述するSQLエンジンで何が問題なのかを理解することです。

表DESCRは次のようになります。

Table P (500 rows) 
pID varchar(50) NOT NULL as primary key 
p.* doesn't matter 

Table Tn (between 2000 and 8000 rows) 
Tn.ID int NOT NULL as primary key 
pID varchar(50) NOT NULL as Foreign key 

[EDIT]私の分析の私のエラーを指しsocial.msdn.microsoft.com上Erland Sommarskogに感謝します。 - その答えについての詳細

を覚えておいてください:
LEFT JOINのフォームを直積

私はいつも同じテーブルにREFEREとしてデカルト積がフィルタリングされた可能性があると仮定して間違っていました。

おかげ

+0

いくつかのデータサンプルとテーブルの統計情報を参照する必要があります – cctan

+0

元のクエリの問題は(唯一の)遅さではありません。また、 'Tx'テーブルに共通の' pID'を持つ行があると、間違った結果をもたらす可能性があります。 –

答えて

2

たぶん、このような何か:

SELECT 
    P.pID, 
    (SELECT COUNT(*) FROM Table1 T1 WHERE P.pID = T1.pID) AS NB1, 
    (SELECT COUNT(*) FROM Table2 T2 WHERE P.pID = T2.pID) AS NB2, 
    (SELECT COUNT(*) FROM Table3 T3 WHERE P.pID = T3.pID) AS NB3, 
    (SELECT COUNT(*) FROM Table4 T4 WHERE P.pID = T4.pID) AS NB4, 
    (SELECT COUNT(*) FROM Table5 T5 WHERE P.pID = T5.pID) AS NB5 

FROM MainTable P 
+0

こんにちはArionに感謝します。 私はまだ質問がなぜとても遅いのだろうかと思っています。 ご存知ですか? – Kilren

+0

さて、おそらく私の主な関心事は、SQLエンジンで何が間違っているのかを理解することです。だからこそ、あなたが私のための答えを持っている場合を除いて、私はそれをもう少し長く開いたままにしておきます。 – Kilren

+0

申し訳ありません。私はあなたがvarchar上のカウントを使用しているので、それにも参加して、グループ化しているからだと思います。あなたは必要以上に仕事をしています。実際に不要な結合で使用するデータを処理しています。あなたがちょうどカウントに興味があるなら、これは望ましい解決策です。 – Arion

1

また、(サブクエリ内)によって最初にグループ化することによって、クエリを書き換え、その後参加できます

SELECT 
    P.pID, 
    T1.NB1, 
    T2.NB2, 
    T3.NB3, 
    T4.NB4, 
    T5.NB5 
FROM MainTable P 
    LEFT JOIN 
    (SELECT pID, COUNT(*) AS NB1 FROM Table1 GROUP BY pID) AS T1 
    ON T1.pID = P.pID 
    LEFT JOIN 
    (SELECT pID, COUNT(*) AS NB2 FROM Table2 GROUP BY pID) AS T2 
    ON T2.pID = P.pID 
    LEFT JOIN 
    (SELECT pID, COUNT(*) AS NB3 FROM Table3 GROUP BY pID) AS T3 
    ON T3.pID = P.pID 
    LEFT JOIN 
    (SELECT pID, COUNT(*) AS NB4 FROM Table4 GROUP BY pID) AS T4 
    ON T4.pID = P.pID 
    LEFT JOIN 
    (SELECT pID, COUNT(*) AS NB5 FROM Table5 GROUP BY pID) AS T5 
    ON T5.pID = P.pID 

これは有用であろうCOUNT(*)以外の集約を結果に含める場合は、より多くの相関サブクエリを実行する必要はありません。

+0

他の集計関数(sumのような)を使う方法は、** Arion **の解決策もあります。 – Kilren

+0

これは動作しますが、 'SELECT'リストに別のサブクエリを追加する必要があります。私はSQL Serverが(COUNTとSUMの両方のために1つのサブクエリのみを実行して)それを適切に最適化するかどうかはわかりません。 –

関連する問題