Answers:
确切的限制确实很难提前确定。
大多数人低估的一件事是索引必须满足的高要求,索引才能成为要在查询中使用的候选对象。
高效(非聚集)索引
提供了很好的选择性,例如只返回总行的很小一部分(<1%,<2%)。如果选择性不是给定的-SQL Server的查询优化器很可能会忽略此索引
理想情况下应该覆盖查询,即返回查询所需的所有列。如果您可以创建一个包含1或2个索引列的索引,并包含另一个少数(2-4)列作为包含列,从而可以覆盖查询,则查询优化器将使用该索引。这也意味着:如果您的代码始终SELECT * .....
用于获取所有列,则使用索引的可能性降低-实际上,
我敢肯定还有很多其他标准-但我相信这两个是最关键的标准。当然,您应该始终正确维护索引(重新组织,重建),并确保与索引相关的统计信息是最新的。
PS:外键列上的非聚集索引是一种特殊情况;默认情况下,我总是建议添加这些内容,因为它们有助于加快参照完整性检查以及JOIN
对FK约束的检查。但是即使在这里,通过添加一些附加的“包含”列以使其更加有用,“扩展”那些FK列索引也是绝对有效的。
您可能会发现只有10行的索引有了改进。
在我的机器上的以下测试中,无索引10.5
的版本以秒为单位完成,而带索引的版本以9.8
秒为单位(在3次运行中一致)。
在这种情况下,索引仅包含1个叶子页,但是由于插槽数组按索引键顺序排序,因此它的存在允许SQL Server仅返回感兴趣的单行,而不是对所有10行执行聚合。
CREATE TABLE T
(
X INT,
Y CHAR(100) NULL
)
INSERT INTO T (X)
SELECT number
FROM master..spt_values
WHERE type='P' AND number BETWEEN 1 AND 10
set nocount on;
DECLARE @I INT, @X INT
DECLARE @Time DATETIME2(7) = SYSUTCDATETIME()
SET @I = 1
WHILE (@I < 1000000)
BEGIN
SELECT @X = MAX(X)
FROM T
SET @I += 1
END
SELECT DATEDIFF(MICROSECOND, @Time, SYSUTCDATETIME())
CREATE CLUSTERED INDEX IX ON T(X)
SET @Time = SYSUTCDATETIME()
SET @I = 1
WHILE (@I < 1000000)
BEGIN
SELECT @X = MAX(X)
FROM T
SET @I += 1
END
SELECT DATEDIFF(MICROSECOND, @Time, SYSUTCDATETIME())
DROP TABLE T