【问题标题】:How to exclude certain index in a given query to see that index's impact如何在给定查询中排除某些索引以查看该索引的影响
【发布时间】:2020-08-19 11:34:51
【问题描述】:

假设我在一个表上有多个索引

我想在执行查询时只排除其中一个

假设我的索引被命名为index_a,index_b,index_c

查询是select * from myTable where columnA='var1'

那么我怎样才能从这个查询中只排除index_b

这里的目的是测试索引的影响。所以我将在同一个查询中运行 2 次查询。在第一个查询中,我将启用索引,而在第二个查询中,我不会启用它。所以包含的实际执行计划会告诉我它们相对于批量查询成本

我在举个例子(实际情况要复杂得多)

【问题讨论】:

  • 这个请求没有意义。为什么要排除索引?
  • drop or disable it?但这似乎是一个XY problem,尤其是考虑到提供的查询。
  • 这对于测试删除索引而不实际删除它的影响可能很有用。
  • 扮演魔鬼的拥护者 - 为什么存在没有经过验证的目的的索引?并且删除索引是显而易见的路径(以一定的代价),因此只关注一个查询并尝试“避免”索引是非常可疑的。
  • 忽略此处给出的示例查询。这里的目的是直接比较指数的影响和没有指数的影响。我添加了一张图片来更好地说明问题

标签: sql sql-server tsql indexing sql-server-2017


【解决方案1】:

选项:

  • 索引提示(多个索引提示是个坏主意,请参阅link
  • 禁用索引
  • 删除索引(不推荐用于测试,可能是一个需要一些时间来重新创建索引的大表)
  • 复制架构和数据,要排除的索引除外。 (相关性较低,因为新创建的索引的统计数据会有所不同)

索引提示

您可以尝试使用特定索引执行查询以测试差异:

select * 
from myTable WITH (INDEX(index_a)) -- or index_b or index_c
where columnA='var1'

或者有多个提示:

select * 
from myTable WITH (INDEX(index_a, index_c)) -- Bad idea, only for testing.
where columnA='var1'

您还可以在 JOIN 上指定索引提示,请参阅table hintsquery hints 的文档

禁用索引

禁用索引:

ALTER INDEX index_b ON myTable   
DISABLE;

要启用索引,请参阅documentation

【讨论】:

  • 这里的目的是测试索引的影响。所以我将在同一个查询中运行 2 次查询。在第一个查询中,我将启用索引,而在第二个查询中,我不会启用它。所以包含的实际执行计划将向我展示它们相对于批量查询成本
  • 在测试查询时(在单独的环境中),请确保您正在针对干净的环境进行测试。通过清除缓存并启用统计信息来比较正确的数字。查看DBCC DROPCLEANBUFFERSDBCC FREEPROCCACHE 以清除缓存。和SET STATISTICS TIME ONSET STATISTICS IO ON 获取实际时间。确保您也是数据库中唯一活跃的人,因为您不会测试锁定。
  • 我添加了一张图片来更好地说明
  • 根据图片,如果你想使用Relative batch % cost来比较,你仅限于索引提示,因为ALTER INDEX也会收到一个%。您更擅长比较 I/O 统计数据。
  • 我明白了。所以我必须输入每个索引名称才能进行比较。所以没有可用的排除提示对吗?
猜你喜欢
  • 2011-04-24
  • 2012-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-10
  • 2021-08-31
相关资源
最近更新 更多