MySQL索引:为什么多列索引的性能比单列索引差?

时间:2019-01-30 21:12:07

标签: mysql sql indexing

我正在学习索引,我想尝试使用MySQL Sakila数据库进行实验。我有以下查询:

SELECT title, release_year
FROM film
WHERE release_year < 2010
AND rating = 'R';

这是我尝试的第一个索引:

CREATE INDEX idx_releaseYear ON film(rating);

当我运行查询时,MySQL EXPLAIN返回以下内容:

enter image description here

编辑:我对这些结果的解释:MySQL使用索引(按评分排序)快速查找所有“ R”级电影,然后检查索引返回的每一行的发行年份。

接下来,我创建了一个关于rating和release_year的索引:

CREATE INDEX idx_releaseYear ON film(rating, release_year);

当我运行查询时,MySQL EXPLAIN返回以下内容:

enter image description here

编辑:我的期望:MySQL将使用索引(按评分,然后按release_year排序)快速查找所有“ R”级电影和release_years <2010,并且仅使用电影表从由以下项返回的行中检索电影标题:索引。尽管数据库中的所有电影都具有相同的release_year,但我认为按评分对索引进行排序,然后对发行年份进行排序会比作为第一个查询更好(或者至少通过使用索引的第一列也是如此),因为在第一个查询中查询它必须以随机顺序检查发布年份。

为什么第一个单列索引的性能优于第二个多列索引?我认为他们的表现至少会相同,因为评级是第一位的。

您应该了解一件事:数据库中的所有影片都是2006年发行。

2 个答案:

答案 0 :(得分:5)

这个评论太长了。

表中有195行。我不知道您的数据结构,但是很可能所有行都适合一个数据页面,也许可以容纳两行。

索引不适用于该大小的数据。它们旨在使查询在大得多的数据集上运行得更快。使用索引会有一些开销。例如,MySQL需要同时加载数据页和索引页才能运行查询。减少读取的页面数量可能不会节省任何费用。

道德很简单。不要在很小的查询中判断性能。在这种情况下,通常不需要索引,因为它们具有额外的开销。

答案 1 :(得分:1)

您的“期望”是正确的。 EXPLAIN不精确;不要太信任它。

WHERE release_year < 2010
  AND rating = 'R'

(通常)最好用

进行优化
INDEX(rating,   -- first, because it is tested with '='
      release_year)   -- last, because it is a range.

如果您可以负担得起两种方法的运行,那么观看SESSION STATUS LIKE 'Handler%'可以使您精确地查看所读取的行(并可能写入临时表)。我将讨论该技术here。该博客还解释说综合指数是最好的。

最好的例外:

  • 也许统计数字表明使用索引不值得付出努力;只需扫描表格可能会更好。
  • 也许将其扩展为“覆盖”会更好。 (不适用于相关查询。)
  • 也许PRIMARY KEY应该是那对列,或者至少从它们开始。这样可以避免在索引BTree和数据BTree之间跳动。

如果表只有一千行,则可能看不到该索引,该索引甚至没有索引之间的差异。但是,如果您希望表格增加,最好是最好建立 now 索引,而不是在您的网站出现性能问题并且忘记了详细信息的下半年,

旁注...如果您坚持使用ORDER BY release_year LIMIT 5,则复合索引确实很出色。这是因为该索引可用于所有WHERE,所有ORDER BY并到达LIMIT,并且仅触摸5行。几乎所有其他情况都需要在临时表中收集很多行,对其进行排序,然后剥离5行。