【问题标题】:What is the difference in sql performance between asc and descasc和desc在sql性能上有什么区别
【发布时间】:2013-02-19 17:47:29
【问题描述】:

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

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 Key Lookup (Clustered).. cost: 67%

【问题讨论】:

  • 基础表的原生排序顺序是什么?如果是 asc,则 desc 查询将需要先构建整个结果集,然后才能对其进行 desc 排序。
  • explain planexecution plan :你可以在那里查看..
  • @MarcB 什么是“基础表的本机排序顺序”?您是指聚集索引的键吗?
  • 您的前两个示例不是存储过程,它们只是参数化查询。它们仍然可以有一个缓存的执行计划,但它们不是存储过程。
  • 好的,所以第二个参数化查询执行时间很长,而简单的选择语句非常快。

标签: sql sql-server-2008


【解决方案1】:

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

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

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

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

【讨论】:

  • 再次查看我的问题,如果我将存储过程更改为正常选择它执行得非常快,我使用调整引擎检查了此查询并且找不到任何可能的升级方法。但这确实是真的,正常选择非常快,存储过程31秒。
  • @kosnkov 这听起来可能是参数嗅探,然后(存储的执行计划对于以后执行不是最优的)。使用变量屏蔽参数或使用 OPTIMIZE FOR UNKNOWN sqlservercentral.com/blogs/practicalsqldba/2012/06/27/…
  • @kosnkov 关于参数嗅探的另一个问题,特别是与使用 OPTION (RECOMPILE) 的内联参数化查询有关:stackoverflow.com/questions/10933366/…
  • 我会告诉你更多,如果我在 [Timestamp] 之后添加 while 空格,最后一行看起来像这样: ORDER BY [t0].[Timestamp] ',N'@p0 int', @p0=1161 那么它也只工作一秒钟,这是空白的问题,太棒了。
  • @kosnkov 对查询的任何更改都会导致生成不同的计划。您的数据配置文件是否发生了显着变化,以至于执行计划不是最理想的?您是否查看过实际的执行计划?
猜你喜欢
  • 2012-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-02
  • 2017-01-20
  • 1970-01-01
  • 2019-08-06
  • 2016-12-25
相关资源
最近更新 更多