2016-06-20 21 views
-1

我試圖在大表中找到所有相關記錄並基於較小的記錄集更新它們,但只要我這樣做,所有的性能就會從窗口中消失,開始做一個巨大的桌子全表掃描。防止使用臨時表進行全表掃描

下面的表會是什麼樣子導入文件3之後的示例(有上VoidID列名和文件名以及索引)

該表顯示,ID#1與ID#2反之亦然,對於ID#4和#5也是如此。 ID#3是一個沒有空缺的銷售。

在導入File3後,我想查找所有記錄,在同一個文件中有銷售和空白,但僅限於剛導入的文件。所以,我使用的是臨時表#Results這裏我只插入來自文件3的ID的,但是當我補充一點,臨時表到查詢,它的表的全掃描和需要永遠運行:

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 

這可行,但全表掃描現在仍在運行(超過一個小時),所以這是不可接受的。估計的執行計劃顯示沒有缺失索引。

如何改進此查詢?

**編輯實際的查詢,Key和指數**

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' 

請試試這個本應該吸菸快

,如果他們總是成對出現,你可以做

and p2.id < P1.ID 

這應該是很容易

你有VoidID作爲第二個 - 沒有開玩笑,你有一個索引掃描
要麼使其成爲第一或有一個單獨的索引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這樣做呢?