【问题标题】:Any way to stop a Index Seek with a range predicate?有什么方法可以用范围谓词停止索引搜索?
【发布时间】:2016-06-24 19:18:10
【问题描述】:

SQL Server 2008 R2

我将两个巨大的表连接在一起......查询看起来像:

SELECT ...
FROM Parent p
INNER JOIN Child c ON c.ID = p.ID
<further joins>
WHERE p.ID IN (9558207665, 9558213992, 9558245267, 9558291779, 9558403049)

两个表在 ID 上都有聚集索引。

查询计划正在创建聚集索引查找(在子表上,很有趣),但使用的范围谓词从 9558207665 到 9558403049。这会导致读取 400,000 多条记录,因为子表有多个记录给定的 ID。这导致了一个问题,尤其是当我指定了我想要的实际 5 个 ID 时。

我能够让它不这样做的唯一方法是创建一个具有 5 个 ID 的表变量并将其用作初始 FROM 表,并链接到它。

我了解,出于某种原因,统计数据表明范围会比单独查找更快,但由于最终选择错误,是否有其他方法可以强制搜索进行单独查找?

【问题讨论】:

  • 您是否更新了表格的统计信息?
  • 没有。它太大了。但是,我更感兴趣的是强迫计划服从我的意愿!此外,当统计数据发生变化或其他原因导致重新编译时,我们都享受过完美查询的乐趣。我想避免这种情况。
  • 您可以在查询中使用 HINTS。在MSDN 上阅读它。
  • 我没有找到可接受的提示。不过谢谢。如果您对特定提示有任何想法,我很乐意看看。
  • 您要避免的是让 SQL Server 正确适应不断变化的数据。如果您的表格统计信息没有及时更新,那么这就是您应该解决的问题。

标签: sql sql-server indexing


【解决方案1】:

在处理大型表时,使用小的相关范围连接,有时需要添加看似多余的过滤器。

SELECT ...
FROM Parent p
INNER JOIN Child c ON c.ID = p.ID
<further joins>
WHERE p.ID IN (9558207665, 9558213992, 9558245267, 9558291779, 9558403049)
AND c.ID IN (9558207665, 9558213992, 9558245267, 9558291779, 9558403049)

【讨论】:

  • 我确实发现了这一点,但我真的很想把它放到一个视图中。我无权访问内部表来执行此操作。好主意,不过……如果没有更好的办法,我会把它标记为答案。
  • 如果您从视图中公开子 ID 列而不是父 ID,会发生什么情况?
  • 我可以使用它,但不确定它是否会有所帮助。我可以把两者都暴露出来,然后用你的把戏。
猜你喜欢
  • 2020-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-16
  • 2018-11-10
  • 2010-11-05
相关资源
最近更新 更多