索引在什么时候变得有效

Sea*_*VDH 9 index sql-server

我发现很多资源都提到向表添加索引会使搜索更快,插入更慢,但前提是表很大。这造成了一种权衡,这是一个设计决定,但应该有一个近似的表大小,在此之前使用索引是荒谬的。(例如,10 行可能远低于该限制)

有没有人知道这个限制在哪里,或者知道有什么资源可以为我指明正确的方向?

mar*_*c_s 12

确切的限制真的很难提前确定。

大多数人低估的一件事是索引在成为查询中使用的候选之前必须满足的高要求。

高效(非聚集)索引

  • 提供了很大的选择性,例如只返回总行数的很小百分比(< 1%,< 2%)。如果选择性不是给定的 - SQL Server 的查询优化器很可能会忽略此索引

  • 理想情况下应该覆盖查询,即返回查询所需的所有列。如果您可以创建一个具有 1 或 2 个索引列的索引,并包含另外几个 (2-4) 列作为包含列,因此您可以覆盖查询 - 那么查询优化器很可能会使用此索引。这也意味着:如果您的代码总是SELECT * .....用于获取所有列,则使用索引的可能性会下降 - 实际上非常显着

我相信还有很多其他标准 - 但我相信这两个是最关键的。当然,您应该始终妥善维护您的索引(重新组织、重建),并确保与您的索引相关的统计数据是最新的。

PS:外键列上的非聚集索引是一种特殊情况;默认情况下,我总是建议添加这些,因为它们有助于加快参照完整性检查,以及JOIN's 在那些 FK 约束上的速度。但即使在这里,通过添加一些额外的“包含”列来“扩展”那些 FK 列索引是绝对有效的,以使它们更有用。

  • 虽然这个答案可能不会直接回答问题,但通过给出索引的重要设计原则,并回答了我首先应该提出的问题,它会做得更好。 (2认同)

Mar*_*ith 6

您可能会看到只有 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
Run Code Online (Sandbox Code Playgroud)