【问题标题】:SQL Server ignoring index and performs table scanSQL Server 忽略索引并执行表扫描
【发布时间】:2017-08-03 14:48:15
【问题描述】:

我们的一个查询有一点问题,该查询是通过System.Data.SqlClient.SqlCommand 在 .Net (4.5) 应用程序中执行的。

问题是,查询将执行非常慢的表扫描。所以执行计划在这里显示了Table-Scan

截图:

详情:

所以文本显示,过滤器到 Termine.DatumTermine.EndDatum 导致表扫描。但是为什么 SQL-Server 会忽略索引呢? Termine.DatumTermine.EndDatum 上有两个索引。我们还尝试使用 DatumEndDatum 组合添加第三个。

索引都是非聚集索引,两个字段都是DateTime

【问题讨论】:

  • 显然statistics 已过时!!.. 更新统计信息尝试再次运行查询
  • 同时发布查询和索引详细信息以获得更准确的响应。在这里分享执行计划brentozar.com/pastetheplan
  • 两个单独的索引肯定无济于事,因为您正在尝试两个范围查询。单个组合索引可能有用,但不保证有用。
  • 此外,在更新统计信息后,您可以在该特定计划上运行 DBCC FREEPROCCACHE,然后再次执行该计划以构建新的、正确的
  • 我明天会拿到完整的执行计划。然后我会粘贴它。 (在我们自己的数据库上,查询速度很快,行数更多)

标签: sql-server indexing full-table-scan


【解决方案1】:

它根据估计的行数 124844 决定表扫描,而您的实际行数仅为 831。

优化器认为遍历 124844 最好在表中扫描而不是 Index Seek。

还需要检查除索引之外选择的其他列。如果您选择了除 Index 之外的其他列,则它必须在执行索引查找后执行 RID 查找,优化器可能会认为它更愿意使用表扫描而不是 RID 查找。

第一个修复:更新统计信息并为优化器提供足够的信息以选择更好的计划。

【讨论】:

    【解决方案2】:

    你能提供完整的查询吗?我看到您正在提取一系列跨越 3 个月 的数据。如果此范围在数据集中占很大比例,则可能是由于您尝试返回如此大比例的数据而正在扫描。如果索引的选择性不够,它将不会被拾取。

    还有……

    您在过滤器中有一个OR 子句。通过查看您提供的屏幕截图中的谓词,您似乎可能在两个不同的过滤器周围缺少()。这也可能导致扫描。

    还有一件事... OR 子句有时会导致错误的计划 - 另一种方法是将查询拆分为两个 UNIONED 查询,每个查询都包含不同的 OR。如果您提供查询,我应该能够给您一个重写的版本来显示这一点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多