为啥 TOP 或 SET ROWCOUNT 使我的查询如此缓慢?

Posted

技术标签:

【中文标题】为啥 TOP 或 SET ROWCOUNT 使我的查询如此缓慢?【英文标题】:Why does TOP or SET ROWCOUNT make my query so slow?为什么 TOP 或 SET ROWCOUNT 使我的查询如此缓慢? 【发布时间】:2009-11-18 23:09:37 【问题描述】:

我有一个大约有 1400 万行的 SQL Server 2008 数据库。里面有两张表

Table1
    rowId int, primary key
    someData1 int
    someData2 int...

Table2
    id int, primary key
    rowId ==> int, refers to the rowId from Table1
    someCalculatedData int...

    Table2.rowId is not a foreign key, but I did make a Non-clustered, Non-Unique index on it

当我导入数据时,我将所有数据插入到 Table1 中,然后在 Table2 中找到没有条目的行并将数据插入到该表中。

我通过一次选择 250,000 行、处理数据并将它们插入到 Table2 中,然后找到接下来的 250,000 行,依此类推,直到它们在 Table1 中没有任何行没有任何条目见表 2。

select TOP 250000 rowId from Table1 
       where NOT EXISTS (select rowId from Table2 where Table1.rowId=Table2.rowId)

这个查询确实变慢了,现在需要两分钟多的时间才能获得下一批。 如果我在没有 TOP 或 SET ROWCOUNT 关键字的情况下运行查询并获取所有行,则查询会在大约 15 秒内返回结果。

有谁知道为什么 TOP 和 SET ROWCOUNT 会导致查询花费比获取所有数据更长的时间?

我能否提高查询的性能,但每次仍然只能获取数据的一个子集?

【问题讨论】:

查询是在约 15 秒内返回所有行,还是 开始 返回行,第一个行在 15 秒后返回? 如果我在 Sql Server Management Studio 中运行查询,我可以在 5-8 秒后看到一些结果,并且在没有 TOP 关键字的情况下全部在 15 秒后看到。如果我包含 TOP 关键字,我在 2 分钟内什么都看不到 它不可能在 15 秒内返回 14 百万行,这意味着必须只剩下很少的满足插入条件的行。为什么不直接插入它们,不带顶部子句? 现在我有大约 180 万行在 Table1 中但不在 Table2 中。如果我在本地/在 SSMS 中的同一个框中运行查询,我会在 15 秒内获得 180 万行(只有 rowId 列)。 我不确定为什么 TOP 会引入这种差异。显然,计划发生了变化,我怀疑合并连接被嵌套循环连接和/或查询的 MAXDOP 更改。是否可以发布两个查询计划,一个慢的和一个快的? 【参考方案1】:

看看有没有帮助

select top 250000 t1.rowid 
from Table1 t1 
left outer join table2  t2 
on t1.rowid=t2.rowid 
where t2.rowid is null

【讨论】:

这是个好建议。 “不存在”尤其是在子查询中可能会很慢。 “null join where null”会给你同样的东西。 正是我推荐的!!!根据您设置的索引,此开关可能会产生很大的不同。【参考方案2】:

发生这种情况是因为所有查询都需要在服务器上运行,然后服务器才能确定“前”250,000 行是哪些。只有这样,数据才会开始通过网络返回到您的客户端。

如果没有“top”语句,服务器将立即开始发送数据,尽管我怀疑所有数据从服务器发送并由您的机器接收的总时间可能与包括 top 的语句相似。

【讨论】:

很遗憾没有。无论是服务器在 1400 万行中工作,还是您的客户端机器在做这件事,都必须完成。 如果我选择 Table1 中的所有 rowID 而不是 Table2 中的所有 rowID,则本地和远程查询似乎都可以接受。如果我尝试获取其中的任何一个子集,则需要更长的时间。【参考方案3】:

显然我的索引或 Table2.rowId 上的索引统计信息不新鲜,TOP/SET ROWCOUNT 查询的查询计划执行不佳。

我重新组织/重建了索引,TOP/SET ROWCOUNT 查询的查询性能大大提高。

【讨论】:

如果有人能解释所发生的细微差别和/或如何诊断/更快地识别这些问题,请分享:)

以上是关于为啥 TOP 或 SET ROWCOUNT 使我的查询如此缓慢?的主要内容,如果未能解决你的问题,请参考以下文章

为啥这个 WHERE 子句会使我的查询慢 180 倍?

rowcount和@@rowcount的区别

SQL Server中Rowcount与@@Rowcount的用法

SQL Server中Rowcount与@@Rowcount的用法

为啥我必须执行两次按钮功能才能使我的逻辑正常工作?

为啥意图使我的应用程序崩溃?