0

我有两个非常相似的查询:

exec sp_executesql N'SELECT TOP (1) [t0].[Production]
FROM [dbo].[T_Production] AS [t0]
WHERE [t0].[InputID] = @p0
ORDER BY [t0].[Timestamp] DESC',N'@p0 int',@p0=1161

exec sp_executesql N'SELECT TOP (1) [t0].[Production]
FROM [dbo].[T_Production] AS [t0]
WHERE [t0].[InputID] = @p0
ORDER BY [t0].[Timestamp]',N'@p0 int',@p0=1161

第一个在 1 秒内执行,另一个在 31 秒内执行,为什么?

有趣的是,如果我将第二个查询从存储过程更改为

SELECT TOP (1) [t0].[Production]
FROM [dbo].[T_Production] AS [t0]
WHERE [t0].[InputID] = 1161
ORDER BY [t0].[Timestamp]

它也在 1 秒内执行

但令人惊奇的是,如果在 [Timestamp] 之后添加空格,使最后一行看起来像这样ORDER BY [t0].[Timestamp] ',N'@p0 int',@p0=1161,它的执行速度也非常快。

编辑:经过一番调查,我检查了实际的执行计划,cos 是:select cost:0 -> top cost 6 -> index scan (NonClustered)[T_Production].[_dta_index_T_Production] cost 94

所以我在 [Timestamp] 上添加了降序的新索引。花了几分钟,现在查询的执行速度与第一个查询一样快。

但是在这里我真的很困惑,我现在注意到附加索引的顺序应该是升序的,因为我已经有了降序,但是创建另一个索引有帮助吗?它让我很困惑,所以我删除了我刚刚创建的这个索引,现在这个查询仍然像第一个查询一样快地执行。也许重建索引有帮助?这个问题将再次出现。

但是现在添加和删除索引后,实际执行计划不同:select :cost 0 -> top cost: 0 -> nested loops (inner join) cost 0 -> Index seek (NonClustered)... cost 33% and密钥查找(集群).. 成本:67%

4

1 回答 1

3

索引在键中的列上也有 ASC 和 DESC,这可能会影响执行计划。

对于这样一个简单的查询,这似乎是一个很大的不同,但看看索引定义和执行计划,可能必须有一个代价高昂的额外排序操作。

删除索引几乎肯定会使缓存中的执行计划无效。

为避免参数嗅探,您可以使用OPTION (RECOMPILE)内联参数化查询或将代码移动到存储过程中,然后OPTIMIZE FOR UNKNOWN

于 2013-02-19T17:51:12.510 回答