相关疑难解决方法(0)

添加通配符(或顶部)时 SQL Server 查询速度大幅减慢

我有一个由 2000 万只动物组成的动物园,我在 SQL Server 2005 数据库中对其进行跟踪。其中约 1% 是黑色,约 1% 是天鹅。我想获得所有黑天鹅的详细信息,因此不想淹没我所做的结果页面:

select top 10 * 
from animal 
where colour like 'black'  
and species like 'swan'
Run Code Online (Sandbox Code Playgroud)

(是的,不明智的是,这些字段是自由文本,但它们都已编入索引)。事实证明我们没有这样的动物,因为查询在大约 300 毫秒内返回一个空集。如果我使用 '=' 而不是 'like',它的速度会快两倍,但我有一种预感,后者将为我节省一些打字的时间。

原来动物园管理员认为他可能将一些天鹅输入为“黑色”,因此我相应地修改了查询:

select top 10 * 
from animal  
where colour like 'black%' 
and species like 'swan'
Run Code Online (Sandbox Code Playgroud)

结果证明它们都没有(实际上除了“黑色”动物之外没有“黑色%”动物)但查询现在需要大约 30 秒才能返回空。

似乎只是 'top' 和 'like %' 的组合引起了麻烦,因为

select count(*) 
from animal  
where colour like 'black%' 
and species like 'swan'
Run Code Online (Sandbox Code Playgroud)

返回 0 非常快,甚至

select * 
from animal 
where colour like 'black%' 
and species …
Run Code Online (Sandbox Code Playgroud)

sql-server-2005 sql-server

52
推荐指数
2
解决办法
3885
查看次数

TOP 如何(以及为什么)影响执行计划?

对于我尝试优化的中等复杂查询,我注意到删除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

36
推荐指数
2
解决办法
1万
查看次数

为什么这个查询不使用我的非聚集索引,我该如何做?

作为这个关于提高查询性能的问题的后续,我想知道是否有办法让我的索引默认使用。

此查询在大约 2.5 秒内运行:

SELECT TOP 1000 * FROM [CIA_WIZ].[dbo].[Heartbeats]
WHERE [DateEntered] BETWEEN '2011-08-30' and '2011-08-31';
Run Code Online (Sandbox Code Playgroud)

这个运行在大约 33 毫秒内:

SELECT TOP 1000 * FROM [CIA_WIZ].[dbo].[Heartbeats]
WHERE [DateEntered] BETWEEN '2011-08-30' and '2011-08-31' 
ORDER BY [DateEntered], [DeviceID];
Run Code Online (Sandbox Code Playgroud)

[ID] 字段 (pk) 上有一个聚集索引,[DateEntered],[DeviceID] 上有一个非聚集索引。第一个查询使用聚集索引,第二个查询使用我的非聚集索引。我的问题是两部分:

  • 为什么,因为两个查询在 [DateEntered] 字段上都有一个 WHERE 子句,服务器是否在第一个而不是第二个上使用聚集索引?
  • 即使没有orderby,如何在此查询中默认使用非聚集索引?(或者为什么我不想要这种行为?)

index sql-server optimization sql-server-2008-r2

14
推荐指数
2
解决办法
3万
查看次数