如何检测MySQL索引是否必要或必需?

时间:2016-01-30 10:36:36

标签: mysql indexing

如何检测是否需要或需要MySQL索引?

我们认为可以改进一些查询。而且我知道我可以在慢速查询日志中潜水......但我在MS SQL下面的帖子中搜索过,并且想知道是否有一种简单的方法来分析是否需要索引(并且会立即提高速度)当前的MySQL数据库。

帮助表示赞赏

MS SQL资源:https://dba.stackexchange.com/questions/56/how-to-determine-if-an-index-is-required-or-necessary

2 个答案:

答案 0 :(得分:4)

你不能。

有一些方法可以在一段时间内检测索引是否使用。但是无法确定索引未使用。假设您有一个每月一次的任务,可以对表进行一些重大维护。而且你真的需要一个特定的索引来防止任务锁定表并关闭应用程序。如果您在一个月的大部分时间检查了索引使用情况,但未能包含该用法,则可能认为您不需要索引。然后你会放弃索引...并抱歉。 (这是一个真实的轶事。)

同时,对索引有一些简单的规则......

    如果您还有INDEX(a) ,则
  • INDEX(a,b)是不必要的 如果您还有INDEX(id)PRIMARY KEY(id),则
  • UNIQUE(id)是不必要的。
  • 可以使用具有5列或更多列的索引,但不太可能“有用”。 (缩短它。)
  • INDEX(a), INDEX(b) INDEX(a,b)相同。
  • INDEX(b,a) INDEX(a,b)相同;你可能需要两者。
  • INDEX(flag),其中flag具有少量不同的值,可能永远不会被使用 - 优化程序将会扫描表格。
  • 在许多情况下,“前缀”索引(INDEX(foo(10)))是无用的。 (但也有很多例外。)
  • “我为每一列编制索引” - 一种糟糕的设计模式。
  • 通常,但并非总是如此,同时使用PRIMARY KEYUNIQUE键意味着某些内容不是最优的。
  • InnoDB表确实应该有一个明确的PRIMARY KEY
  • InnoDB隐式地在任何辅助密钥中包含PK。因此,鉴于PRIMARY KEY(id)INDEX(foo)实际上是INDEX(foo, id)
  • 有时,优化工具会忽略WHERE子句并使用ORDER BY的索引。
  • 某些查询具有偏差属性,优化程序将根据不同的常量使用不同的索引。 (我确实在一个查询中看到多达6种不同的解释计划。)
  • “索引合并相交”几乎总是不如复合索引。
  • 大多数提示都有例外。

所以,我更愿意接受所有查询(SELECTsUPDATEsDELETEs),决定每个查询的最佳索引,消除冗余等,以便查找“最佳”索引集。请参阅my cookbook on creating an index, given a SELECT

答案 1 :(得分:0)

你肯定应该花一些时间阅读索引,有很多关于它的文章,并且了解正在发生的事情很重要。

从广义上讲,索引会对表的行强制排序。

为简单起见,想象一个表只是一个大的CSV文件。每当插入一行时,它就会插入到最后。因此,表的“自然”排序只是插入行的顺序。

想象一下,您已经在一个非常基本的电子表格应用程序中加载了该CSV文件。所有这些电子表格都显示数据,并按顺序对行进行编号。

现在假设您需要在第三列中找到所有具有某些值“M”的行。鉴于您的可用性,您只有一个选项。您扫描表格,检查每行的第三列的值。如果你有很多行,这种方法(“表扫描”)可能需要很长时间!

现在想象一下,除了这个表,你还有一个索引。此特定索引是第三列中的值的索引。索引以一些有意义的顺序(例如,按字母顺序)列出第三列中的所有值,并且对于每个值,它提供了该值出现的行号列表。

现在您有一个很好的策略来查找第三列的值为“M”的所有行。例如,您可以执行二进制搜索!虽然表扫描要求您查看N行(其中N是行数),但二进制搜索仅要求您查看log-n索引条目,在最坏的情况下。哇,这肯定容易多了!

当然,如果你有这个索引,并且你正在向表中添加行(最后,因为这是我们的概念表的工作原理),你需要每次都更新索引。因此,当您编写新行时,您会做更多的工作,但是当您搜索某些内容时,可以节省大量时间。

因此,通常,索引会在读取效率和写入效率之间进行权衡。没有索引,插入可以非常快 - 数据库引擎只是向表中添加一行。在添加索引时,引擎必须在执行插入时更新每个索引。

另一方面,阅读变得更快。