0

実行に約3分かかるクエリがあります。クエリはレポートに使用されており、より効率的にしたいと思います。ボトルネックは内側の結合だと思います。あなたたちが解決策を持っているかどうかを知りたいだけで間違っている可能性があります。

    SELECT DISTINCT 
    SUBSTRING(T1.DateTime, 1, 4) AS Year, 
    SUBSTRING(T1.DateTime, 5, 2) AS Month, 
    SUBSTRING(T1.DateTime, 7, 2) AS Day, 
    T1.PipeNr, T1.SalesOrder, T1.JobNr, SIST.DefectCode AS DefectRef, 
    DEFCODES.DefectCode, DEFCODES.DefectDesc, SIST.ODYes, SIST.LocationWrap, 
    T1.OWS0601, T1.OWS0602, T1.OWS0603, T1.CrossWeld

    FROM PIPEDB.dbo.SIST INNER JOIN PIPEDB.dbo.MPIPEID T1 ON PIPEDB.dbo.SIST.PipeNr = T1.PipeNr INNER JOIN 
    PIPEDB.dbo.DEFCODES ON PIPEDB.dbo.SIST.DefectCode = PIPEDB.dbo.DEFCODES.DefectRef

    WHERE PIPEDB.dbo.SIST.DefectCode
    IN (
    SELECT Top (10) PIPEDB.dbo.SIST.DefectCode

    FROM PIPEDB.dbo.SIST INNER JOIN PIPEDB.dbo.MPIPEID T2 ON PIPEDB.dbo.SIST.PipeNr = T2.PipeNr INNER JOIN 
    PIPEDB.dbo.DEFCODES ON PIPEDB.dbo.SIST.DefectCode = PIPEDB.dbo.DEFCODES.DefectRef

    WHERE SUBSTRING(T2.DateTime, 1, 4) = SUBSTRING(T1.DateTime, 1, 4) AND SUBSTRING(T2.DateTime, 5, 2) = SUBSTRING(T1.DateTime, 5, 2) AND 
    SUBSTRING(T2.DateTime, 7, 2) = SUBSTRING(T1.DateTime, 7, 2)

    GROUP BY PIPEDB.dbo.SIST.DefectCode

    ORDER BY COUNT(PIPEDB.dbo.SIST.PipeNr) DESC) 

    AND (PIPEDB.dbo.DEFCODES.DefectDesc IN ("Cut To Remove Defect")) AND 
    ((CASE WHEN T1.CrossWeld = 1 THEN 1 WHEN T1.CrossWeld = 0 THEN 2 END) = @Crossweld OR @Crossweld = 0)
4

3 に答える 3

1

問題は、INサブクエリを相関サブクエリとして作成しているため、パフォーマンスの問題が発生していることです。メイン句の(または外部の)行ごとに、INサブクエリが実行されているため、時間がかかります。内部サブクエリは、テーブルのサイズに基づいてコストがかかる可能性があり、おそらくサブクエリでネストされたループ結合を使用します。また、外部クエリの行数が非常に多い場合は、高価なINサブクエリが長時間実行されているため、クエリのパフォーマンスが低下します。ロジックをもう一度確認して、正しい結果が得られていることを確認することをお勧めします。データ。

以下を参照してください。私はあなたの問題を再現しようとしました。このクエリのコストは2045であり、非常に高額であり、もちろん時間がかかります。これは、約1,000万ioの176秒のCPUと48秒の経過時間を計測します。

それではありません.10個のproductid(欠陥コードは10個しかないと思います)がありますが、相関サブクエリのために、他の多くのproductidが表示される可能性があります。

set statistics io,time on

go

select * from Sales.SalesOrderHeader soh inner join sales.SalesOrderDetail sod
on sod.SalesOrderID=soh.SalesOrderID
where sod.ProductID in (
select top 10 ProductID
from Sales.SalesOrderHeader soh1 inner join sales.SalesOrderDetail sod
on sod.SalesOrderID=soh1.SalesOrderID
where datepart(yy,soh.OrderDate) = DATEPART(yy,soh1.OrderDate)
and datepart(mm,soh.OrderDate) = DATEPART(mm,soh1.OrderDate)

)。

   order by sod.ProductID
于 2012-07-20T19:18:53.507 に答える
0

次の手順に従って、SQLServerがインデックスを推奨していることを確認してください。

Microsoft SQL ServerManagementStudioのクエリウィンドウにクエリを配置します。

実行する代わりに、CTRL + Lを押します(またはメニューから[クエリ]> [推定実行プランの表示]を選択します)。

次に、[実行プラン]タブに、緑色で「Missing Index(Impact xx.xxxx%)...」で始まるテキストが表示される場合があります。その場合は、そのテキストを右クリックして[MissingIndexDetails]を選択しますこれにより、提案されたインデックス定義を含む新しいウィンドウが開きます(インデックス名を指定する必要があります)。例:

/*
Missing Index Details from SQLQuery3.sql - (local).master (sa (55))
The Query Processor estimates that implementing the following index could improve the query cost by 99.3783%.
*/

/*
USE [DatabaseName]
GO
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[Table] ([Column1])
INCLUDE ([Column2],[Column2])
GO
*/

'<欠落しているインデックスの名前、sysname、>'を有効なインデックス名に置き換えて、インデックスを作成します。

これらの手順は、インデックスが提案されなくなるまで繰り返すことができます。

それを超えて、where句でSubStringを使用することはおそらく問題です。

これ:

WHERE SUBSTRING(T2.DateTime, 1, 4) = SUBSTRING(T1.DateTime, 1, 4) AND SUBSTRING(T2.DateTime, 5, 2) = SUBSTRING(T1.DateTime, 5, 2) AND SUBSTRING(T2.DateTime, 7, 2) = SUBSTRING(T1.DateTime, 7, 2)

間違いなくこれである可能性があります:

WHERE SUBSTRING(T2.DateTime, 1, 8) = SUBSTRING(T1.DateTime, 1, 8)

またはさらに良い:

WHERE LEFT(T2.DateTime, 8) = Left(T1.DateTime, 1, 8)

またはさらに良い(より多くのインデックスの使用を許可できます):

WHERE T2 LIKE Left(T1.DateTime, 1, 8) + '%'

また、これらの日付文字列の長さが8文字しかない場合は、次のようになります。

WHERE T2.DateTime = T1.DateTime

それでもクエリが目的の時間に実行されない場合は、where句でSUBSTRINGまたはLEFTが不要になるようにデータを再構築することをお勧めします。つまり、独自の列で日付を分割します。

于 2012-07-20T19:10:41.140 に答える
0

あなたは持っている必要がありDISTINCTますか?むしろGROUP BY、一意のレコードのセットを返すために使用したいです。

SELECT DISTINCT X
FROM Y

への変更

SELECT X
FROM Y
GROUP BY X

また、一般的にわずかに高速であるため、句で使用するよりも使用EXISTSする方が好きです。INWHERE

次のセクションをに入れて、 / setupの代わりにCTEパーティション関数を使用したくなるでしょう。RANK() OVERTOP(10)ORDER BY

IN (
SELECT Top (10) PIPEDB.dbo.SIST.DefectCode

FROM PIPEDB.dbo.SIST INNER JOIN PIPEDB.dbo.MPIPEID T2 ON PIPEDB.dbo.SIST.PipeNr = T2.PipeNr INNER JOIN 
PIPEDB.dbo.DEFCODES ON PIPEDB.dbo.SIST.DefectCode = PIPEDB.dbo.DEFCODES.DefectRef

WHERE SUBSTRING(T2.DateTime, 1, 4) = SUBSTRING(T1.DateTime, 1, 4) AND SUBSTRING(T2.DateTime, 5, 2) = SUBSTRING(T1.DateTime, 5, 2) AND 
SUBSTRING(T2.DateTime, 7, 2) = SUBSTRING(T1.DateTime, 7, 2)

GROUP BY PIPEDB.dbo.SIST.DefectCode

ORDER BY COUNT(PIPEDB.dbo.SIST.PipeNr) DESC)
于 2012-07-20T19:32:18.670 に答える