指数实际上会降低SELECT性能吗?

时间:2012-07-06 11:41:05

标签: sql sql-server performance select indexing

  

可能重复:
  Degraded performance of a query after adding Index

在阅读了有关SQL Server索引的一些内容以及它们对更新/插入的选择和缺点的性能优势之后,我想知道使用不当的索引是否实际上也会损害选择的性能。 如果索引降低纯选择查询的性能,必须满足哪些条件?存在这样的情况吗?

谢谢!

(虽然我总是尝试包含代码示例,但我想不出任何可以支持这个问题的内容......)

5 个答案:

答案 0 :(得分:13)

是的,虽然非常轻微 - 但是有点理由也回答“不”。

如果你有一个可能被认为是查询的索引但是不可用,那么优化器将浪费很短的时间来思考是否以及如何使用它(在极少数情况下使用非常复杂的索引)和视图,并且当索引性能提示错误时更频繁,您最终可能会选择次优的查询计划。)

有些情况会是:

  • 没有索引的表
  • 一个包含错误选择索引的表,将被丢弃
  • 存在两个索引的表,由于某种原因(例如过时的统计信息),第二个索引的存在使优化器选择它,而使用第一个索引会更方便。

在前两种情况下,查询时间是相同的(并且需要完整扫描),但在第二种情况下,您还必须分析并丢弃索引。

索引会伤害你 - 所有索引伤害你的地方 - 是插入,删除和更新。然后,更新查询未使用但受其影响的任何索引都需要写入索引本身。

所以你会希望拥有索引,但是尽可能少而不牺牲SELECT性能。实际上,您可能决定不使用很少使用的SELECT查询的索引,以避免所有其他UPDATE查询不断更新所需的索引。

编辑:在阅读Heinzi的回答之后,我还想补充一点,大多数数据库服务器都有维护工具来分析表和索引(有时也会查询性能计数器),并正确更新Heinzi所说的提示。因此,定期“维护”数据库以保持优化器提供有关可供选择的索引的最新信息也很重要。

更新(MySQL)

有一个非常漂亮的MySQL分析工具,它实际上可以建议对现有索引进行改进(删除未使用的密钥,添加有用的密钥):common_schema。这真的值得一看。

答案 1 :(得分:4)

是的,但这不太可能,也不会影响您使用索引的决定。

有时,SQL Server查询分析器会选择不是最佳的执行计划。由于可能的执行计划的数量比第一眼看上去的要大得多(n表的简单连接已经产生n!可能的执行计划),SQL Server 已经做出有根据的猜测。猜测的本质是它们有时是错误的。

这种情况很少发生,但过去几年我发现它发生过几次。在那种情况下(并且仅在那种情况下),如果指数不在那里,则会选择更好的计划。 然而,删除索引是解决此问题的正确方法,因为索引通常存在是有原因的。正确的方法是为此查询添加提示(并且仅针对此查询),以帮助优化程序选择正确的计划。

答案 2 :(得分:2)

是的,索引可能会损害SELECT的性能。了解数据库引擎的运行方式非常重要。数据存储在“页面”中的磁盘上。通过索引,可以访问表中一列或多列中具有特定值的特定页面。

如果您正在寻找特定值,这非常棒。

但是,请考虑需要查看表中每一行的查询。如果您浏览表格,则按顺序阅读页面 - 关键 - 您只需一次阅读即可获得页面上的每一行。读取次数是表中的页数。此外,页面缓存可以通过先行读取优化读取,并且不再使用的页面被简单地覆盖。

使用相同读取的索引一次通过表一条记录而不是一次一页。这导致随机读取页面。在最坏的情况下,表中每条记录只读一次 - 可能是对性能的重大打击。另外,索引本身占用了一些页面缓存,减少了其他操作的内存。

通常,SQL引擎的优化器组件可以很好地区分这两种情况。其中一个关键指标是查询的选择性。返回的查询有多少行(优化程序根据页数查看)?如果行数与页数大致相同,优化程序将考虑进行全表扫描而不是索引扫描。

肯定有其他注意事项,但一般来说,索引可能会损害即使是简单的选择查询的性能。一般来说,优化器做得很好,但有时会出现异常情况甚至是最好的优化器。

答案 3 :(得分:1)

我的猜测是,如果您创建的索引会混淆查询计划优化器,最终会为手头的查询选择一个低效的索引。

答案 4 :(得分:1)

这可能与实现有关,但原则上索引不应该减慢SELECT

显然,他们可以放慢INSERTUPDATE