2016-04-22 18 views
0
 SELECT 
s.ColID1 
,s.ColIdentification2 
,s.StatusColumn 
,(SELECT 
    MAX(pd.DateColumn) 
    FROM DocumentTable pd 
    WHERE pd.IsPresent = 1 
    AND pd.ColIdentification2 = s.ColIdentification2 
    AND pd.TypeofFile = 'TextFiles') 
AS maxDate 
,(SELECT TOP 1 
    u.Title 
    FROM DocumentTable pd 
    LEFT OUTER JOIN [User] u 
    ON u.UserId = pd.UserId 
    WHERE pd.IsPresent = 1 
    AND pd.ColIdentification2 = s.ColIdentification2 
    AND pd.TypeofFile = 'Text Files' 
    ORDER BY pd.DateColumn DESC) 
AS Name1 
,(SELECT TOP 1 
    pd.DocumentType 
    FROM DocumentTable pd 
    WHERE pd.IsPresent = 1 
    AND pd.ColIdentification2 = s.ColIdentification2 
    AND pd.TypeofFile = 'Text Files' 
    ORDER BY pd.DateColumn DESC) 
, (SELECT TOP 1 
    pd.TypeofFile 
    FROM DocumentTable pd 
    WHERE pd.IsPresent = 1 
    AND pd.ColIdentification2 = s.ColIdentification2 
    AND pd.TypeofFile = 'Text Files' 
    ORDER BY pd.DateColumn DESC) 
,(SELECT TOP 1 
    pd.Region 
    FROM DocumentTable pd 
    WHERE pd.IsPresent = 1 
    AND pd.ColIdentification2 = s.ColIdentification2 
    AND pd.TypeofFile = 'Text Files' 
    ORDER BY pd.DateColumn DESC) 
,(SELECT TOP 1 
    pd.Agency 
    FROM DocumentTable pd 
    WHERE pd.IsPresent = 1 
    AND pd.ColIdentification2 = s.ColIdentification2 
    AND pd.TypeofFile = 'Text Files' 
    ORDER BY pd.DateColumn DESC) 
FROM Service s (NOLOCK) 
--left outer join DocumentTable pd1 (NOLOCK) 
--on pd1.ColIdentification2 = s.ColIdentification2 
WHERE s.IsPresent = 1 
--AND pd1.ColIdentification2 = s.ColIdentification2 
AND s.StatusColumn IN ('Val1', 'Val3') 
AND NOT EXISTS (SELECT 
    pd.DocumentTableId 
FROM DocumentTable pd 
WHERE pd.IsPresent = 1 
AND pd.ColIdentification2 = s.ColIdentification2 
AND pd.TypeofFile IN ('DC1', 'DC2')) 
AND NOT EXISTS (SELECT 
    utds.ID 
FROM utds 
WHERE utds.Service_x0020_ID1_Id = s.ColID1 
AND utds.Type IN ('DC1', 'DC2')) 
ORDER BY s.ColID1 

このSQLを最適化しようとしています。サブクエリの数が多いため、時間がかかります。このクエリは実行に10分以上かかるし、私はそれを改善しようとしています。とにかくサブクエリを避ける。私はテーブル間の左外部結合を使用しようとしましたが、DocumentTableのColID1のデータが重複しているため、正しいデータが得られません。トランザクションSQL時間の問題

答えて

0

統計情報を持たないクエリをチューニングするのは難しいです実行計画と試行錯誤。

私が考えることは、サブクエリを結合することでよりうまくいくということです。したがって、サブクエリを排除しようとします。

あなたはそれが助け場合は、同じアプローチを使用してみたクエリ

SELECT s.ColID1 
    , s.ColIdentification2 
    , s.StatusColumn 
    , pd.DocumentType, pd.TypeofFile, pd.Region, pd.TypeofFile, Region 
from [Service] s 
    outer apply (select top 1 DocumentType, TypeofFile, Region, TypeofFile, Region 
       from DocumentTable 
       where IsPresent = 1 and TypeofFile = 'Text Files' 
        and ColIdentification2 = s.ColIdentification2 
       order by DateColumn desc) pd 

の下に使用した結合4を取り除くことができます。

また、両方のテーブルのColIdentification2フィールドにインデックスがあることを確認してください。

+0

ありがとうございます。私たちはcolIdentification2フィールドを主キーとして指定しており、それにクラスター化インデックスがあります。 。私はドキュメントテーブルのこの列に非クラスタ化インデックスを作成しようとします。私はあなたに同意する、私は統計情報を作成します。前回のアウタージョイントから外してみたところ、結果セットは異なっていました。しかし、私はあなたの提案でそれを試してみます – Nate

0

Flickerは、ColIdentification2のような一般的な列にインデックスが付いているかどうかを確認する上で非常に重要なポイントです。また、DocumentTable.DateColumnのインデックスがあることを確認したいと思います。だから、

SELECT 
s.ColID1 
,s.ColIdentification2 
,s.StatusColumn 
,(SELECT TOP 1 u.Title   FROM DocumentTable pd LEFT OUTER JOIN [User] u ON u.UserId = pd.UserId WHERE pd.IsPresent = 1 AND pd.ColIdentification2 = s.ColIdentification2 AND pd.TypeofFile = 'Text Files' ORDER BY pd.DateColumn DESC) AS Name1 
,(SELECT MAX(pd.DateColumn) FROM DocumentTable pd WHERE pd.IsPresent = 1 AND pd.ColIdentification2 = s.ColIdentification2 AND pd.TypeofFile = 'TextFiles') AS maxDate 
,(SELECT TOP 1 pd.DocumentType FROM DocumentTable pd WHERE pd.IsPresent = 1 AND pd.ColIdentification2 = s.ColIdentification2 AND pd.TypeofFile = 'Text Files' ORDER BY pd.DateColumn DESC) 
,(SELECT TOP 1 pd.TypeofFile FROM DocumentTable pd WHERE pd.IsPresent = 1 AND pd.ColIdentification2 = s.ColIdentification2 AND pd.TypeofFile = 'Text Files' ORDER BY pd.DateColumn DESC) 
,(SELECT TOP 1 pd.Region  FROM DocumentTable pd WHERE pd.IsPresent = 1 AND pd.ColIdentification2 = s.ColIdentification2 AND pd.TypeofFile = 'Text Files' ORDER BY pd.DateColumn DESC) 
,(SELECT TOP 1 pd.Agency  FROM DocumentTable pd WHERE pd.IsPresent = 1 AND pd.ColIdentification2 = s.ColIdentification2 AND pd.TypeofFile = 'Text Files' ORDER BY pd.DateColumn DESC) 
FROM Service s (NOLOCK) 
WHERE s.IsPresent = 1 
    AND s.StatusColumn IN ('Val1', 'Val3') 
AND NOT EXISTS (SELECT utds.ID FROM utds WHERE utds.Service_x0020_ID1_Id = s.ColID1 AND utds.Type IN ('DC1', 'DC2')) 
ORDER BY s.ColID1 

:任意のレートで

...

物事はあなたのクエリであり少し忙しい、のは、それを少し再フォーマットし、それを「全体像」を見てみましょう彼らはすべてのDocumentTable PDに同じ行から来ることになりますように、次の列が見える:

pd.DateColumn 
pd.DocumentType 
pd.TypeofFile 
pd.Region  
pd.Agency  

note: For pd.DateColumn, your use of max(pd.DateColumn) has the result same 
     the sub-select style you're using in the other pd.* columns: 
     SELECT TOP 1 pd.DateColumn from ...BLAH BLAH BLAH... order by pd.DateColumn DESC 
Also your pd.DateColumn's subselect has a where clause checking for 'TextFiles' 
instead of 'Text Files' that the other pd.* columns are using, should they all 
be 'Text Files'? (Note the extra embedded space in 'TextFiles' vs 'Text Files') 

の代わりに実行されているPDのための同じサブクエリロジック5異なる時間、しています

:これは完全にテストされていないコードがところである

...のJOINを左にそれをプッシュし、一度それをやってみましょう、私はそれが:-)

SELECT 
    s.ColID1 
, s.ColIdentification2 
, s.StatusColumn 
/* If we get a stable row for PD pulling u.Title from User becomes easier... */ 
, (select u.Title from User u where on u.UserId = pd.UserId) as userTitle 
, pd.DateColumn 
, pd.DocumentType 
, pd.TypeofFile 
, pd.Region 
, pd.Agency 
FROM Service s (NOLOCK) 
left join DocumentTable pd 
     on pd.IsPresent = 1 
     and pd.ColIdentification2 = s.ColIdentification2 
     and pd.TypeofFile = 'Text Files' 
     /* This next condition avoids having to do the ORDER BY pd.DateColumnDESC 
     * The idea is for sqlserver to consider all potential matching pd records 
     * but ignore any that aren't the largest date. 
     */ 
     and not exists(select 1 from DocumentTable pd2 
         where pd2.IsPresent   = pd1.IsPresent 
         and pd2.ColIdentification2 = pd.ColIdentification2 
         and pd2.TypeofFile   = pd.TypeofFile 
         and pd2.DateColumn   > pd.DateColumn) 
     /* may as well add the "no DC1 & DC2" clause here... */ 
     and not exists (select 1 FROM DocumentTable pd3 
         where pd2.IsPresent   = pd1.IsPresent 
         and pd2.ColIdentification2 = pd.ColIdentification2 
         and pd2.TypeofFile   in ('DC1', 'DC2') 
         and pd2.DateColumn   > pd.DateColumn) 
WHERE s.IsPresent = 1 
    AND s.StatusColumn IN ('Val1', 'Val3') 
    AND NOT EXISTS (
    SELECT 1 FROM utds 
    WHERE utds.Service_x0020_ID1_Id = s.ColID1 
     AND utds.Type     IN ('DC1', 'DC2')) 
ORDER BY s.ColID1 

少数決算の考えを作品願っています私は複雑なWHERE句をインデントするのが好きで、論理の周りに私の頭を包み込むのが簡単になります。 我々は最大で(見つけるしたいと思う私たちは「S」から取得した各レコードの

select * FROM Service s 

を:メインテーブル「s」は何をしているかで動作する、クエリの行動について考えるように

)適切な「pd」レコード。

ここで「適切」とは、pd.ColIdentification2 = s.colIdentificationなどの一般的な列を意味します。

微妙な部分はこれです:ここ

AND NOT EXISTS (SELECT 1 FROM DocumentTable PD2 ....WHERE PD2.DATECOLUMN > PD.DATECOLUMN). 

一つの高速化の利点は、我々はおよそORDER BYない本当にケアを行うで、私たちは(私たちが使用して、我々は、PDに最新の行を持っていることを確認したいです実行中の古いpdレコードを蹴飛ばすためのpd2の存在しないもの)。

私はこれがORDER BYより速くなることができると思う理由は、SQL ServerエンジンがORDER BY DATECOLUMN DESC「にTOP 1を処理するためのインデックストラバーサルを行う必要はありませんで、巧妙なオプティマイザは多分それを把握し、ちょうどにジャンプすることができDATECOLUMNの最大インデックス...それは多分大きいので、このアプローチが全体的に速くなると期待しています)。

DC1またはDC2があるPDレコードをブロックする同様のトリックに注意してください。

元のクエリでは、その部分を(最後のWHERE句の最後に)読みます:「指定されたPDレコードがあらゆる点で完璧ですPD/Sの一致が「DC1」または「DC2」(日付に関わらず)であれば、すべてのPD/Sレコードを削除したいと考えています。

関連する問題