对于我尝试优化的中等复杂查询,我注意到删除TOP n
子句会更改执行计划。我猜想,当查询包含TOP n
数据库引擎时,会运行查询而忽略该TOP
子句,然后最后将结果集缩小到请求的n行数。图形执行计划似乎表明情况确实如此——TOP
是“最后”一步。但似乎还有更多事情发生。
我的问题是,TOP n 子句如何(以及为什么)影响查询的执行计划?
这是我的情况的简化版本:
查询匹配来自两个表 A 和 B 的行。
如果没有该TOP
子句,优化器估计将有来自表 A 的 19k 行和来自表 B 的 46k 行。返回的实际行数是 A 的 16k 和 B 的 13k。哈希匹配用于连接这两个结果集总共 69 行(然后应用排序)。此查询发生得非常快。
当我添加TOP 1001
优化器时不使用哈希匹配;相反,它首先对表 A 的结果进行排序(与 19k/16k 相同的估计值/实际值)并对表 B 执行嵌套循环。表 B 的估计行数现在为 1,奇怪的是TOP n
直接影响对 B 的估计执行次数(索引搜索) - 它似乎总是2n+1,或者在我的情况下是 2003 年。如果我改变,这个估计会相应地改变TOP n
。当然,由于这是嵌套连接,因此实际执行次数为 16k(表 A 中的行数),这会减慢查询速度。
实际场景有点复杂,但这捕获了基本思想/行为。两个表都使用索引查找进行搜索。这是 SQL Server 2008 R2 企业版。
performance sql-server optimization execution-plan query-performance
我有一个观点,complicated_view
-- 有一些连接和 where 子句。现在,
select * from complicated_view (9000 records)
Run Code Online (Sandbox Code Playgroud)
更快,更快,比
select top 500 * from complicated_view
Run Code Online (Sandbox Code Playgroud)
我们说的是 19 秒对 5+ 分钟。
第一个查询返回所有 9000 条记录。如何只获得前 500 名的时间长得可笑?
显然,我将在这里查看执行计划 ---- 但是一旦我弄清楚为什么SQL Server 以次优方式运行“前 500”,我该如何实际告诉它以快速方式运行计划,喜欢坐满桌?
当然,我可能不得不完全重写视图——但很奇怪。
基本上,我将此数据表连接到第 3 方软件,该软件使用select top 500 *
无法修改的默认查询预先检查表。因此,除了将此视图转储到实际表中(非常草率)之外,我也无法绕过他们的“前 500 名”附录。
这是 SQL Server 2012。
编辑:不同意重复标志。另一个问题,顶部比所有的都快。这将是预期的行为,返回较少的行。我的情况正好相反。另外,我的理解是 Top 100 是一种与 Top 100+ 不同的算法。我什至不认为重复的问题有正确的答案。也就是说,TOP X 查询将在很早的时候对潜在的大量表进行排序,而不是在它们被聚合/过滤/等之后。为什么是一个谜,但如何显然存在。
performance sql-server execution-plan select top query-performance