6

我使用下一个查询从 DB 中提取前 100 和 101 行并获得以下经过时间,这完全不同(第二个查询比第一个慢约 8 个):

SELECT TOP (100) *
 FROM PhotoLike WHERE photoAccountId=@accountId AND accountId<>@accountId
 ORDER BY createDate DESC
GO

SQL Server 执行时间:CPU 时间 = 187 毫秒,经过时间 = 202 毫秒。

SELECT TOP (101) *
 FROM PhotoLike WHERE photoAccountId=@accountId AND accountId<>@accountId
 ORDER BY createDate DESC
GO

SQL Server 执行时间:CPU 时间 = 266 毫秒,经过时间 = 1644 毫秒。

前两种情况的执行计划: 使用变量选择前 100 和 101

但是,如果我摆脱 @accoundId 变量,我会得到以下结果,它大约等于并且比这个问题的第一个查询快 2 倍以上。

SELECT TOP (100) *
 FROM PhotoLike WHERE photoAccountId=10 AND accountId<>10
 ORDER BY createDate DESC
GO

SQL Server 执行时间:CPU 时间 = 358 毫秒,经过时间 = 90 毫秒。

SELECT TOP (101) *
 FROM PhotoLike WHERE photoAccountId=10 AND accountId<>10
 ORDER BY createDate DESC
GO

SQL Server 执行时间:CPU 时间 = 452 毫秒,经过时间 = 93 毫秒。

后两案执行计划: 选择前 100 和 101 没有变量

为什么会发生这种情况,如何使用变量提高性能?

更新

添加了执行计划。

4

3 回答 3

2

这里发生了几件事。

当您使用变量时,SQL Server 根本不会嗅探这些值,除非您还添加OPTION (RECOMPILE).

与实际情况相比,猜测的匹配行数的估计值photoAccountId=@accountId要小得多。(注意第二个计划中索引搜索的粗线以及使用并行计划的决定)。

另外TOP 100/TOP 101是使用只需要空间来对 100 行进行排序的算法和它进行完整排序之间的分界点。不准确的行数估计可能意味着为完整排序分配的内存不足,并且溢出到.TOP Ntempdb

简单地将OPTION (RECOMPILE)变量添加到查询中可能会有所改善,尽管看起来即使“快速”计划也在执行许多可以通过不同索引避免的键查找。

于 2013-08-08T13:19:11.310 回答
0

我可以,您应该根据表的 accountId 字段创建一个聚集索引。

当您测试不等式时,它应该更高效:

在 [dbo].[PhotoLike] 上创建唯一聚集索引 [IX_MyIndexName](accountId DESC、createDate DESC、photoAccountId DESC、)

于 2013-08-08T15:35:33.423 回答
0

我想知道这是否与参数嗅探有关。以下查询的速度有多快?

DECLARE @accountIdParam int;
SELECT @accountIdParam = @accountId;

SELECT TOP (101) *
FROM PhotoLike WHERE photoAccountId=@accountIdParam AND accountId<>@accountIdParam
ORDER BY createDate DESC
GO
于 2013-08-08T12:53:53.550 回答