2016-06-20 3 views
-1

大きなテーブルのすべての関連レコードを見つけて、それを小さなレコードセットに基づいて更新しようとしていますが、すぐにすべてのパフォーマンスがウィンドウに表示され、大規模なテーブルの完全なテーブルスキャンを開始します。以下テーブル全体のスキャンを行う一時テーブルとの結合を防止する

テーブルはFILE3をインポートした後にどのように見えるかの例である(VoidID列とファイル名のインデックスが同様にあります)

テーブルは、ID#1はID#2に関連して表示されているとID#4と#5と同じです。 ID#3は無効な売却です。

File3をインポートした後、同じファイルに販売と無効が存在するが、インポートされたばかりのファイルについてのみ、すべてのレコードを探したいとします。だから私は、私だけFILE3からIDを挿入する一時テーブル#Resultsを使用していますが、私は、クエリにその一時テーブルを追加するとき、それはテーブルのフルスキャンを行い、実行するために永遠に取ります

DECLARE @Import Table(ID int PRIMARY KEY NOT NULL, TransType varchar(10), VoidID int, FileName varchar(25)) 
INSERT INTO @Import 
VALUES(1,'Sale',2,'File1'),(2,'Void',1,'File1'),(3,'Sale',NULL,'File2'),(4,'Sale',5,'File3'),(5,'Void',4,'File3') 
SELECT * FROM @Import 

CREATE table #Results(ID integer PRIMARY KEY NOT NULL) 
INSERT INTO #Results(ID) 
SELECT ID FROM @Import WHERE FileName = 'File3' 

select * from #Results 

SELECT P1.ID 
FROM @Import P1 INNER JOIN #Results R ON P1.ID = R.ID INNER JOIN @Import P2 ON P1.ID = P2.VoidID 
WHERE P1.FileName = P2.FileName 

DROP TABLE #Results 

これは動作しますが、フルテーブルスキャンは今でも(1時間以上)実行されているので、実際には受け入れられません。推定された実行計画には、欠落しているインデックスはありません。

このクエリを改善するにはどうすればよいですか?

** EDIT実際のクエリ、キー、およびインデックス**

UPDATE P1 
SET Notes = 'Matching Sale, Void in same file.' 
FROM 
PriceImport P1 INNER JOIN 
#ResultSet R ON P1.ID = R.ID INNER JOIN 
PriceImport P2 ON P1.ID = P2.VoidID 
WHERE P1.FileName = P2.FileName 


ALTER TABLE [dbo].[PriceImport] ADD CONSTRAINT [PK_PriceImportID] PRIMARY KEY NONCLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO 

CREATE NONCLUSTERED INDEX [idx_PriceImport_Transaction_Matching] ON [dbo].[PriceImport] 
(
    [TransType] ASC, 
    [VoidID] ASC 
) 
INCLUDE ([ID]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO 
+0

実行計画を見て、テーブルスキャンの原因を調べてみてください。あなたは、テーブルまたは一時テーブルにインデックスがありませんか? –

+0

'EXCEPTS'構文を見るのも有益でしょう。場合によっては、より高速になる可能性があります。 – Shaneis

+0

あなたは本当に 'WHERE P1.FileName = P2.FileName'を必要とします – JamieD77

答えて

0

私は私はあなたがやろうとしているものを手に入れる#TEMP
の必要性を得ていないのですが、それは
必要はありません それらの列がインデックス化されている場合、これは速い

喫煙する必要がある

select p2.id, P1.ID 
    from table p1 
    join table p2 
    on P1.ID = P2.VoidID 
    and p1.filename = 'File3' 
    and p2.filename = 'File3' 

あなたの本当のテーブルの上にこれを試してみてくださいあなたはインデックス・スキャン
を持っているのいずれか、それが最初またはメイク冗談を - 彼らはペアで常にある場合、10

あなたが

and p2.id < P1.ID 

を行うことができ、これは2番目としてVoidIDを持っていない

簡単にする必要がありますあなたはテーブルが

下さいPOをスキャンなっているノー冗談 - あなたは、ファイル名にはインデックスがありませんVoidID
用に別のインデックスを持っていますSTは、この

UPDATE P1 
SET Notes = 'Matching Sale, Void in same file.' 
FROM PriceImport P1 
JOIN #ResultSet R 
     ON P1.ID = R.ID 
JOIN PriceImport P2 
     ON P1.ID  = P2.VoidID 
     AND P1.FileName = P2.FileName 
     AND isnull(Notes, "") <> 'Matching Sale, Void in same file.' 

へのクエリプランは#ResultSet場合、ファイル名ならば、これは

UPDATE P1 
SET Notes = 'Matching Sale, Void in same file.' 
FROM PriceImport P1 
JOIN #ResultSet R1 
     ON P1.ID = R1.ID 
JOIN PriceImport P2 
     ON P1.ID = P2.VoidID 
     AND isNull(Notes, "") <> 'Matching Sale, Void in same file.' -- locks are expensive 
JOIN #ResultSet R2 
     ON P2.ID = R2.ID 

あなたは#ResultSetでこれをやって、すべて#ResultSetをロードすると考えられてきた方が良いでしょうか?

関連する問題