它必须扫描整个表,因为它不是 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
。