我试图在一个大表中查找所有相关记录并根据较小的记录集更新它们,但是一旦我这样做,所有性能都会从窗口中消失并开始执行全表扫描大规模的桌子。
下面是导入file3后表格的示例(还有VoidID列和FileName的索引)
该表显示ID#1与ID#2相关,反之亦然,ID#4和#5相同。 ID#3是一个无效的销售。
导入File3之后,我想查找同一文件中存在销售和无效的所有记录,但仅针对刚刚导入的文件。所以我使用临时表#Results,我只从File3插入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
这样可行,但全表扫描现在仍然在运行(超过一小时),所以这是不可接受的。估计的执行计划显示没有丢失的索引。
如何改进此查询?
**编辑实际查询,密钥和索引**
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)
我不需要#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具有单独的索引
你没有文件名索引 - 不开玩笑你正在进行表扫描
请将查询计划发布到此
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?