我正在学习索引,我想尝试使用MySQL Sakila数据库进行实验。我有以下查询:
SELECT title, release_year
FROM film
WHERE release_year < 2010
AND rating = 'R';
这是我尝试的第一个索引:
CREATE INDEX idx_releaseYear ON film(rating);
当我运行查询时,MySQL EXPLAIN返回以下内容:
编辑:我对这些结果的解释:MySQL使用索引(按评分排序)快速查找所有“ R”级电影,然后检查索引返回的每一行的发行年份。
接下来,我创建了一个关于rating和release_year的索引:
CREATE INDEX idx_releaseYear ON film(rating, release_year);
当我运行查询时,MySQL EXPLAIN返回以下内容:
编辑:我的期望:MySQL将使用索引(按评分,然后按release_year排序)快速查找所有“ R”级电影和release_years <2010,并且仅使用电影表从由以下项返回的行中检索电影标题:索引。尽管数据库中的所有电影都具有相同的release_year,但我认为按评分对索引进行排序,然后对发行年份进行排序会比作为第一个查询更好(或者至少通过使用索引的第一列也是如此),因为在第一个查询中查询它必须以随机顺序检查发布年份。
为什么第一个单列索引的性能优于第二个多列索引?我认为他们的表现至少会相同,因为评级是第一位的。
您应该了解一件事:数据库中的所有影片都是2006年发行。
答案 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行。