MySQL 索引 - 最佳实践是什么?

标签 mysql indexing query-optimization

我在我的 MySQL 数据库上使用索引已有一段时间了,但从未正确地了解它们。通常,我会使用 WHERE 子句在我将要搜索或选择的任何字段上放置一个索引,但有时它看起来并不那么黑白分明。

MySQL 索引的最佳实践是什么?

示例情况/困境:

  • 如果一个表有六列并且所有列都是可搜索的,我应该对所有列进行索引还是不对它们进行索引?

  • 索引对性能有哪些负面影响?

  • 如果我有一个 VARCHAR 2500 列,可以从我网站的某些部分进行搜索,我应该为它建立索引吗?

最佳答案

您绝对应该花一些时间阅读有关索引的内容,关于它的文章很多,理解正在发生的事情很重要。

从广义上讲,索引对表的行进行排序。

为简单起见,将表格想象成一个大的 CSV 文件。每当插入一行时,它都会被插入末尾。因此表的“自然”排序就是插入行的顺序。

假设您已将 CSV 文件加载到一个非常基本的电子表格应用程序中。此电子表格所做的只是显示数据,并按顺序对行进行编号。

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

现在想象一下,除了这张表之外,您还有一个索引。这个特定的索引是第三列中值的索引。该索引以某种有意义的顺序(例如,按字母顺序排列)列出了第三列中的所有值,并为每个值提供了该值出现的行号列表。

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

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

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

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

希望这涵盖了您的前两个问题(正如其他人所回答的那样——您需要找到正确的平衡点)。

您的第三种情况稍微复杂一些。如果您使用 LIKE,索引引擎通常会帮助您将读取速度提高到第一个“%”。换句话说,如果你正在 SELECTing WHERE column LIKE 'foo%bar%',数据库将使用索引查找列以“foo”开头的所有行,然后需要扫描中间行集以找到子集包含“酒吧”。 SELECT ... WHERE column LIKE '%bar%' 不能使用索引。我希望你能明白为什么。

最后,您需要开始考虑多个列上的索引。这个概念是相同的,并且与 LIKE 的行为类似——本质上,如果您在 (a,b,c) 上有一个索引,引擎将继续尽可能地从左到右使用该索引。因此,对 a 列的搜索可能会使用 (a,b,c) 索引,就像对 (a,b) 的搜索一样。但是,如果您搜索 WHERE b=5 AND c=1),引擎将需要进行全表扫描

希望这有助于阐明一些问题,但我必须重申,您最好花几个小时四处寻找能够深入解释这些事情的好文章。阅读特定数据库服务器的文档也是一个好主意。查询规划器实现和使用索引的方式千差万别。

关于MySQL 索引 - 最佳实践是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51512298/

相关文章:

php - MySQL - 如何永久存储缓存?

mysql - SELECT 和 WHERE 中的 SQL CASE 用于选择行

php - mysql 中的数据崩溃

r - 在循环内更改循环索引

mysql - 该子查询如何复制结果?它是否为结果中的每一行发送相同的请求?

mysql - MySql 查询慢(优化 LEFT OUTER JOIN)

php - 安装PHP数据库

mysql - 用于从表中选择的 SQL

java - 替换字符串中特定索引处的字符?

mysql - 主键是否在 MySQL 中自动建立索引?