在SQL Server 2012中比较两个大型结果集的最有效方法是什么


9

当前比较两个大型结果/行集的最有效方法的建议似乎是使用EXCEPT运算符。随着行大小的增加(更改@last值),下面的自包含SQL脚本效率非常低下。我试图在组合表中查找唯一条目,但没有任何改进。

DECLARE @first AS INT, @step AS INT, @last AS INT; 

-- This script is comparing two record sets using EXCEPT
-- I want to find additions from OLD to NEW
-- As number of rows increase performance gets terrible
-- I don't have to use two tables. I could use one combined table but I want the same result as quickly as possible

-- Compare 100 to 110 rows - 0 seconds
-- Compare 1000 to 1010 rows - 1 seconds
-- Compare 10000 to 10010 rows - 16 seconds
-- Compare 100000 to 100010 rows - ABORT after 8 minutes (tables are populated in 18 seconds)

DECLARE @temptableOLD TABLE ([Result1] int);
SET @step = 1;  SET @first = 1; SET @last = 100000
WHILE(@first <= @last) BEGIN INSERT INTO @temptableOLD VALUES(@first) SET @first += @step END

DECLARE @temptableNEW TABLE ([Result1] int);
SET @step = 1;  SET @first = 1; SET @last = 100010
WHILE(@first <= @last) BEGIN INSERT INTO @temptableNEW VALUES(@first) SET @first += @step END

select * from @temptableNEW
except
select * from @temptableOLD

Answers:


8

EXCEPT表示一项DISTINCT操作。

NOT EXISTS如果这实际上不是必需的,我会使用。

但是,您遇到的问题很可能是由于与表变量关联的基数估计不佳,导致在未索引表上出现嵌套循环。

select * from @temptableNEW
except
select * from @temptableOLD
OPTION (RECOMPILE)

将能够考虑到每个表都有10万行,并给出了不同的计划。

在SQL Server 2012中,只能通过约束将索引添加到表变量。如果值是唯一的,则可以使用

DECLARE @temptableOLD TABLE ([Result1] int UNIQUE CLUSTERED);

添加索引。如果在两个表上都完成了该计划(在添加了重新编译提示之后),则可能会使用合并联接。如果没有任何索引,我将期望进行哈希联接。


谢谢马丁。这就是答案。OPTION(RECOMPILE)提供了帮助(5分钟内达到100,000),但是两个表上的UNIQUE CLUSTERED都取得了很大的进步(7秒内达到了100,000 !!!)。我仅创建这些表来演示一个现实问题,其中我无法控制两个不同SQL Server上的表索引,但是我将通过此类表变量进行管理。
Will Healey 2015年

4
@WillHealey #temp表相对于表变量具有很多优势(统计,并行性,更灵活的索引编制),因此,如果您在限于表变量的环境中不使用此表,也可以尝试使用它们。
马丁·史密斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.