为什么创建索引和运行查询比没有它运行查询更快?

Iva*_*nov 2 sql-server sql-server-2017 query-performance

我有几百万行的表。它包含来自外部服务的日志,所以我决定不对其进行索引(大量插入,稀疏读取)。

当我运行从没有索引的表中读取的查询时,它需要(不出所料)很长时间。

但是,当我创建索引并运行查询然后删除索引时,速度要快得多(即使创建和删除索引也是如此)。

为什么创建临时索引更快,而不是让 SQL Server 做它的事情?这似乎不直观(为什么 SQL Server 不自己创建索引?)。这种方法有什么缺点吗?


有问题的查询看起来像这样,但我认为它不一定相关,因为我在其他地方也看到了类似的行为。

    UPDATE Device
    SET Col1 = l.Col1
        ,Col2 = l.Col2
        ,Col3 = l.Col3
    FROM dbo.Device
        OUTER APPLY (
            SELECT MAX(Id) AS [Id]
            FROM dbo.Logs 
            WHERE Logs.Device_FK = Device.Id
            GROUP BY Logs.Device_FK
        ) lastLog
        OUTER APPLY (
            SELECT Col1, Col2, FORMAT(Col3) AS "Col3"
            FROM dbo.Logs
            WHERE Logs.Id = lastLog.Id
        ) l
Run Code Online (Sandbox Code Playgroud)

Tib*_*szi 5

原因是你反复扫描 Logs 表。您甚至在该查询中有两个交叉应用。重复扫描这个表显然比建立索引然后使用该索引更昂贵。

这里没有什么奇怪或意外的。

SQL Server 可能会做一个索引假脱机,以便它可以在每次访问 Logs 表时使用它。也许优化器评估了该策略并放弃了它,因为它的估计表明它不会有好处(可能是错误的)。第一步是研究执行计划,将估计值与实际值进行比较并从中获取。