SQL查询性能/ SELECT TOP X行为

时间:2012-08-14 21:41:36

标签: sql performance sql-server-2008

想知道为什么这个查询执行缓慢。如果有人可以告诉我如何处理它将是伟大的。被查询的DB有超过5亿行。这个查询是否真的写得不好,以至于TOP 10需要很长时间才能完成它可能永远不会完成?假设我仍然想按月+年查询数据,我该如何改进查询?

 SELECT TOP 10 *
 FROM ADB.dbo.Stuff tt
 WHERE MONTH(tt.SomeDate) = 5
 AND
 YEAR(tt.SomeDate) = 2011

在获得10个结果后,SELECT TOP 10不会停止吗?还是需要这么长时间,因为它在通过500米+行时还没有找到我的条件?

感谢并抱歉这么简单的问题。

1 个答案:

答案 0 :(得分:7)

它必须扫描整个表,因为MONTH(column)YEAR(column)不是可搜索的,并且您没有告诉SQL Server TOP是什么意思。虽然SQL Server可能能够短路,但它找到了你的10行,但是当发生这种情况时,它可能会进入扫描范围,这对你来说差别很小。如果您发现零行或<0,则尤其如此。与where子句匹配的10行。

更好的WHERE条款是:

WHERE SomeDate >= '20110501' AND SomeDate < '20110601';

如果您不想构造字符串,可以将它们作为参数/变量传递并执行此操作:

DECLARE @year INT;
DECLARE @month INT;

SET @year = 2011;
SET @month = 5;

...
WHERE SomeDate >= DATEADD(MONTH, @month-1, DATEADD(YEAR, @year-1900, '19000101'))
  AND SomeDate <  DATEADD(MONTH, @month,   DATEADD(YEAR, @year-1900, '19000101'));

在任何一种情况下,如果SomeDate上有索引,则可以使用它,并且可以避免表扫描。您希望避免在具有5亿行的表上进行表扫描,即使您只查找10行,即使可能发生短路。

然而,即使没有表扫描,此查询仍然效率低下。你真的需要所有的专栏吗?如果使用SomeDate上的索引,则搜索仍然必须查找聚簇索引或覆盖索引以检索其余列。如果您不需要这些列,请不要包含它们。

正如bluefeet指出的那样,如果你没有告诉SQL Server 你的意思是哪个 10,那么这个TOP 10的东西是没有意义的,而你使用ORDER BY来做。如果ORDER BY使用了合适的索引,您可以避免使用额外的代价高昂的排序运算符,您可能认为无论如何都不会使用ORDER BY