【问题标题】:Sql Server - Index not being usedSql Server - 未使用索引
【发布时间】:2017-10-24 19:22:37
【问题描述】:

运行以下查询后:

SELECT [hour], count(*) as hits, avg(elapsed)
FROM myTable
WHERE [url] IS NOT NULL and floordate >= '2017-05-01'
group by [hour]

执行计划基本上是PK上的聚集索引扫描(int,自增,97%的工作)

问题是:URL 上面有一个索引(常规索引,因为我总是在搜索完全匹配),floordate 也有一个索引...

为什么不使用它们?如何加快查询速度?

PS:表有 70M 长,这个查询大约需要 9 分钟才能运行

编辑 1
如果我不在索引上使用(选择或过滤)列,它还会被使用吗?通常我也会过滤/分组clientId(整个数据库中大约 300 个唯一)和hour(24 个唯一)...

【问题讨论】:

  • hourElapsed 列呢,如果这些列不包含在您提到的索引中,则需要在聚集索引中查找以获取这些值。
  • 单个列上的索引不会覆盖整个查询(hourelapsed 仍需要查找),如果大多数行有 url NOT NULL 索引在url 上根本没有用。所以这一切都归结为floordate >= '2017-05-01' 将覆盖引擎估计的行数,以及聚集索引查找是否会优于直接扫描它。如果您的统计数据已过时,则此估计可能会大大偏离。在执行任何其他操作之前尝试更新它们(下一个合乎逻辑的步骤是该索引中的 INCLUDE 列)。
  • 您可以将 count(*) 替换为 count(1),这可能有助于改善一些时间..
  • 你能把表模式和索引一起添加吗
  • @JeroenMostert 所说的。此外,请查看索引中的列顺序。根据您的查询方式,实际上没有 url,您的列顺序应该是 floordate,然后是 url。

标签: sql-server performance indexing database-performance


【解决方案1】:

在这种情况下,有两件事会影响 SQL Server 选择索引的方式。

  1. 索引的选择性如何。更高的选择性更好。 NULL/NOT NULL 过滤器通常具有非常低的选择性。
  2. 是索引中的所有列,也称为覆盖索引。

在您的示例中,如果索引无法覆盖查询,SQL 将不得不根据基表查找其他列值。如果您的 URL/Floordate 组合没有足够的选择性,SQL 可能会确定扫描基表比从非聚集索引到基表的大量行进行昂贵的查找更便宜。

在不了解您的架构的其他任何信息的情况下,我建议使用以下列的索引:

floordate, url, hour; include elapsed

日期范围扫描通常比 NULL/NOT NULL 测试更具选择性。将 Floordate 移到前面可能会使该索引更适合此查询。如果 SQL 确定查询适用于 Floordate 和 URL,则 Hour 列可用于 Group By 操作。由于包含了 Elapsed,因此该索引可以完全覆盖查询。

您可以在下班后添加 ClientID,看看这是否对您的其他查询也有帮助。

只要索引包含解析查询的所有列,它就是一个候选者,即使不需要过滤。一般来说,非聚集索引比基表更瘦,比扫描全宽基表需要更少的 IO。

【讨论】:

    猜你喜欢
    • 2011-05-10
    • 2014-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-18
    相关资源
    最近更新 更多