SQL查询性能/ SELECT TOP X行为

Raz*_*zle 0 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
Run Code Online (Sandbox Code Playgroud)

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

谢谢,抱歉这么简单的问题.

Aar*_*and 7

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

一个更好的WHERE条款是:

WHERE SomeDate >= '20110501' AND SomeDate < '20110601';
Run Code Online (Sandbox Code Playgroud)

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

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'));
Run Code Online (Sandbox Code Playgroud)

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

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

而作为bluefeet指出,这个TOP 10东西是没有意义的,如果你还没有告诉SQL服务器你的意思是10,和你做,使用ORDER BY.如果ORDER BY使用合适的索引,您可以避免使用额外的昂贵的排序运算符,您可能认为ORDER BY无论如何都要避免使用它.