我已经在我的MySQL数据库上使用索引有一段时间了,但从来没有正确地学习过它们。一般来说,我把索引放在任何字段,我将搜索或选择使用WHERE子句,但有时它似乎不是那么黑和白。

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

例子的情况/困境:

如果一个表有六列,并且它们都是可搜索的,我应该索引它们全部还是没有? 索引对性能的负面影响是什么? 如果我有一个varchar2500列,可以从我的网站的部分搜索,我应该索引它吗?


当前回答

我不会在其他答案中重复一些好的建议,但我会补充:

复合指标

您可以创建复合索引—包含多个列的索引。MySQL可以从左到右使用这些。如果你有:

Table A
Id
Name
Category
Age
Description

如果你有一个复合索引,按顺序包含名字/类别/年龄,这些WHERE子句将使用索引:

WHERE Name='Eric' and Category='A'

WHERE Name='Eric' and Category='A' and Age > 18

but

WHERE Category='A' and Age > 18

不会使用这个索引,因为所有东西都是从左到右使用的。

解释

使用Explain / Explain Extended来了解MySQL可以使用哪些索引以及它实际选择了哪个索引。MySQL每次查询只使用一个键。

EXPLAIN EXTENDED SELECT * from Table WHERE Something='ABC'

慢速查询日志

打开慢速查询日志,查看哪些查询运行慢。

宽栏

如果您有一个宽列,其中大多数区别发生在前几个字符,您可以在索引中只使用前N个字符。例如:我们有一个定义为varchar(255)的ReferenceNumber列,但是97%的情况下,引用号是10个字符或更少。我将索引更改为只查看前10个字符,从而大大提高了性能。

其他回答

看看像“更多掌握索引的艺术”这样的演讲。

2012年12月更新:我已经发布了我的一个新演示:如何设计索引,真的。2012年10月,我在圣克拉拉的ZendCon和12月的伦敦Percona Live上发表了这篇文章。

设计最佳索引的过程必须与你在应用程序中运行的查询相匹配。

很难推荐任何通用规则,比如哪些列最好索引,或者是否应该索引所有列还是不索引列,哪些索引应该跨多个列,等等。这取决于您需要运行的查询。

是的,有一些开销,所以您不应该创建不必要的索引。但是您应该创建索引,以便快速运行所需的查询。索引的开销通常远远超过它的收益。

对于VARCHAR(2500)列,你可能想使用FULLTEXT索引或前缀索引:

CREATE INDEX i ON SomeTable(longVarchar(100));

请注意,如果您正在搜索可能位于长varchar中间的单词,那么传统的索引就无法提供帮助。为此,使用全文索引。

如果一个表有六列,他们都是可搜索的,我应该索引他们所有或没有

您是逐个字段搜索还是使用多个字段进行搜索? 哪些字段最常被搜索? 字段类型是什么?(例如,索引在int上比在VARCHARs上工作得更好) 您尝试过对正在运行的查询使用EXPLAIN吗?

索引对性能的负面影响是什么

更新和插入将变慢。此外,还需要额外的存储空间,但这在如今通常并不重要。

如果我有一个varchar2500列,可以从我的网站的部分搜索,我应该索引它

不,除非它是唯一的(这意味着它已经被索引),或者你只搜索该字段的精确匹配(不使用LIKE或mySQL的全文搜索)。

通常我把索引放在任何字段,我将搜索或选择使用WHERE子句

我通常会索引查询次数最多的字段,然后是int / boolean / enum,而不是VARCHARS字段。不要忘记,通常需要在组合字段上创建索引,而不是在单个字段上创建索引。使用EXPLAIN,并检查慢日志。

我不会在其他答案中重复一些好的建议,但我会补充:

复合指标

您可以创建复合索引—包含多个列的索引。MySQL可以从左到右使用这些。如果你有:

Table A
Id
Name
Category
Age
Description

如果你有一个复合索引,按顺序包含名字/类别/年龄,这些WHERE子句将使用索引:

WHERE Name='Eric' and Category='A'

WHERE Name='Eric' and Category='A' and Age > 18

but

WHERE Category='A' and Age > 18

不会使用这个索引,因为所有东西都是从左到右使用的。

解释

使用Explain / Explain Extended来了解MySQL可以使用哪些索引以及它实际选择了哪个索引。MySQL每次查询只使用一个键。

EXPLAIN EXTENDED SELECT * from Table WHERE Something='ABC'

慢速查询日志

打开慢速查询日志,查看哪些查询运行慢。

宽栏

如果您有一个宽列,其中大多数区别发生在前几个字符,您可以在索引中只使用前N个字符。例如:我们有一个定义为varchar(255)的ReferenceNumber列,但是97%的情况下,引用号是10个字符或更少。我将索引更改为只查看前10个字符,从而大大提高了性能。

1/2)索引会加速某些选择操作,但会减慢其他操作,如插入、更新和删除。这可以是一个很好的平衡。

3)使用全文索引或狮身人面像

Load Data Efficiently: Indexes speed up retrievals but slow down inserts and deletes, as well as updates of values in indexed columns. That is, indexes slow down most operations that involve writing. This occurs because writing a row requires writing not only the data row, it requires changes to any indexes as well. The more indexes a table has, the more changes need to be made, and the greater the average performance degradation. Most tables receive many reads and few writes, but for a table with a high percentage of writes, the cost of index updating might be significant.

避免索引:如果您不需要特定的索引来帮助查询更好地执行,就不要创建索引。

磁盘空间:一个索引会占用磁盘空间,多个索引会占用更多的空间。这可能会导致您比没有索引时更快地达到表大小限制。尽可能避免使用索引。

建议:不要过度索引