2011-08-15 30 views
7

不思議なパフォーマンスの問題を抱えている特定のSQLクエリがあります。ここでは、クエリは次のとおりです。集計関数を使用してSQLクエリのパフォーマンスを改善する必要があります

SELECT COUNT(LengthOfTime) AS TotalTime, 
     SUM(LengthOfTime) AS TotalLength, 
     SUM(LengthOfTime)/COUNT(LengthOfTime) AS AverageTime, 
     SUM(Pops)/COUNT(LengthOfTime) AS AveragePop 
    FROM ((SELECT * 
      FROM (SELECT *, ID & YearRec AS ID2 
        FROM MyFirstTable 
       UNION ALL 
       SELECT *, ID & YearRec AS ID2 
        FROM Table2011) AS TEMP 
      WHERE STARTTIME >= '8/1/2011 00:00:00' 
      AND StartTime <= '8/5/2011 23:59:59') AS TEMP2 
    JOIN AppleTable ON TEMP2.Reason = AppleTable.Skills) 
    JOIN PeopleTable ON TEMP2.Operator = PeopleTable.Operators 
WHERE AppleTable.[ON] = 1 
    AND PeopleTable.[ON] = 1 
    AND Rec_Type = 'SECRET AGENT' 

ここでの問題は非常にゆっくりと5日間のスパンのために実行したときに、このクエリは非常に迅速に(午前0時02分まで0時00分)走るということですが、(1:45 1:20 )を6日間延長した。

テーブル(MyFirstTableおよびTable2011)には、1日あたり約105,000レコードがあります。

私の質問:あなたは、SQL Serverのパフォーマンスに重大な問題を参照してくださいする前にあなたは、集計関数を渡すことができます行の数に上限はありますか? (現在2008 R2を使用しています)

+0

最新の統計情報ですが、最近インデックスを再構築してもらえますか? –

+0

あなたのようなサウンドは、メモリ内の操作からディスクを必要とするものにあふれているかもしれません。私はMySQLチューニングの詳細に慣れていませんが、一時的なワークスペース用のメモリ割り当てパラメータがある場合は、それを増やすことができます。 –

+1

@Jim:not mySQL ... –

答えて

4

いいえ、集計関数の事前定義された上限はありません。

性能のスキューはおそらく以下の一つまたは複数によって影響される:

    • 古い及び/又は不適切インデックス構造キャッシュされた実行計画を
    • キャッシュデータ
    • データがされていないサイズ(最初の5日間は10行、6行目は100B行)

    クエリを実行できますSSMSで実際の実行計画を表示します。これにより、クエリの実行コストが最も高い場所がわかります。これは、最良の行動方針を決定するのに役立ちます。

    コメントに基づいて編集:

    [STARTTIME]が含まれていTable2011上のインデックスが存在しない場合は、1を作成します。インデックスがあるが無視されている場合は、その理由を把握する必要があります。断片化されている場合は、インデックスを再構築することは間違いありません。ここで

    ALTER INDEX [YourIndexName] ON [dbo].[Table2011] REBUILD WITH (STATISTICS_NORECOMPUTE = ON);

    を再構築する方法である代わりに、あなたはSSMSでこれを行うことができます - 右クリックして、再構築し、オブジェクトブラウザで特定のインデックスを参照します。

    +0

    私は実際の実行計画を見ました。 Costの97%はTable2011の "Table Scan"からのものです。これは、UNION – dan042988

    +0

    @ dan042988の回答が更新される前にStartTimeを述語にしたあとです。 –

    +0

    私に正しい方向を教えていただきありがとうございます。私は、[データベース名] GO は[DBO]。[Table2011]([Rec_Type]、[のStartTime])ON非クラスタ化インデックス[QueryIndex1] は(INCLUDE CREATE新しいインデックス '使用を作成するために、実際の実行計画を使用して終了[オペレータ]、[LengthOfTime]、[Pop]、[Reason]) GO' – dan042988

    9

    短い回答:いいえ、MSSQLのパフォーマンスが低下する原因となる魔法の数はありません。

    これで、クエリのスケールがうまくいかず、その結果、データセットが大きくなり、指数関数的に悪化する可能性があります。

    大きな問題は、UNIONEDステートメントの後にStartTime を宣言していることです。代わりに、UNIONより前の両方の選択でその述語を述語にしてみてください。これは、特にStartTime上で両方のテーブルを索引付けする(索引を作成してこれらの表をシークする)場合、大きな違いがあります。

    SELECT * FROM (
    SELECT *, ID & YearRec AS ID2 FROM MyFirstTable 
        WHERE STARTTIME >= '8/1/2011 00:00:00' 
        AND STARTTIME <= '8/5/2011 23:59:59' 
    UNION ALL SELECT *, ID & YearRec AS ID2 
    FROM Table2011 
        WHERE STARTTIME >= '8/1/2011 00:00:00' 
        AND STARTTIME <= '8/5/2011 23:59:59' 
    ) AS TEMP 
    

    コードのリファクタリングを追加することもできます。

    +0

    +1 - 「WHERE」の位置についての非常に良い点。 –

    +0

    「UNION」の位置を確認するために+1します。さらに2つのテーブルを別々に結合してグループ化し、集約を使用すると、パフォーマンスがさらに向上する可能性があります。 –

    +0

    残念ながら、クエリオプティマイザがこれを処理する必要があります。クエリプランでは、この条件がサブパーシャルの外側に適用されるかどうかを表示する必要があります。連合。パフォーマンスの差をゼロにする必要があります。 – TomTom

    関連する問題