0

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

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

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

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

4

1 回答 1

7

它必须扫描整个表,因为它不是 sargable,MONTH(column)而且YEAR(column)你还没有告诉 SQL Server 你所说的TOP. 虽然 SQL Server 确实可以在找到您的 10 行后进行短路,但当发生这种情况时,它可能会在扫描中进行到很远,以至于对您的差异很小。如果您找到与 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 指出的那样,TOP 10如果您没有告诉 SQL Server您的意思是哪个10,并且您使用ORDER BY. 如果ORDER BY使用合适的索引,您可以避免额外昂贵的排序运算符,您可能认为您通过不使用任何方式来避免ORDER BY

于 2012-08-14T21:51:08.690 回答