为什么MySQL停止“使用分组索引”,尽管这样做效率较低
该表由遗留应用程序使用,因此我们无法更改模式本身 我们有一张大约160万行的桌子为什么MySQL停止“使用分组索引”,尽管这样做效率较低,mysql,Mysql,该表由遗留应用程序使用,因此我们无法更改模式本身 我们有一张大约160万行的桌子 mysql> describe courses_old ; +---------------+------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------------+------------------+----
mysql> describe courses_old ;
+---------------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------+------+-----+---------+-------+
| chapter | varchar(128) | NO | PRI | | |
| label | varchar(128) | NO | PRI | | |
| title | varchar(128) | YES | | NULL | |
| language | varchar(48) | NO | PRI | en | |
+---------------+------------------+------+-----+---------+-------+
我们经常按要求做
SELECT DISTINCT
chapter,
title,
language
FROM courses_old;
它非常慢,所以我们在这3个字段上添加了一个索引,它变得更快,解释如下:
+----+-------------+-------------+-------+----------------+---------------+---------+------+-------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+-------+----------------+---------------+---------+------+-------+--------------------------+
| 1 | SIMPLE | courses_old | range | idx_c_t_l_old | idx_c_t_l_old | 919 | NULL | 65072 | Using index for group-by |
+----+-------------+-------------+-------+----------------+---------------+---------+------+-------+--------------------------+
我们发现有很多50%!没有使用的值,所以我们做了以下工作
将表格重命名为“旧”
再次创建名为this time的表将是新的
正在插入课程\u新选择*从课程\u旧选择,其中。。。
重新创建相同的索引
行数现在是840000,现在解释如下
SELECT DISTINCT
chapter,
title,
language
FROM courses_new;
+----+-------------+-------------+-------+----------------+---------------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+-------+----------------+---------------+---------+------+-------+-------------+
| 1 | SIMPLE | courses_new | index | idx_c_t_l_new | idx_c_t_l_new | 919 | NULL | 809549| Using index |
+----+-------------+-------------+-------+----------------+---------------+---------+------+-------+-------------+
请求从0.2秒变为1秒
然而,如果我现在这样做
SELECT DISTINCT
chapter,
title,
language
FROM courses_new
FORCE INDEX (idx_c_t_l);
性能恢复正常,以及解释
+----+-------------+-------------+-------+----------------+---------------+---------+------+-------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+-------+----------------+---------------+---------+------+-------+--------------------------+
| 1 | SIMPLE | courses_new | range | idx_c_t_l_new | idx_c_t_l_new | 919 | NULL | 101194| Using index for group-by |
+----+-------------+-------------+-------+----------------+---------------+---------+------+-------+--------------------------+
所以我的问题是
为什么MySQL突然决定停止做同样的解释,尽管它效率较低?
有没有办法通过使用一些参数等让MySQL回归理性,找到最有效的查询计划?
编辑:某些精度:
我保留了两个版本的表,因此它们在完全相同的条件下运行
新桌子上的行比旧桌子上的少
我已经对每个请求进行了1000次基准测试,以确保没有导致性能差异的缓存
由于数据增长,它可能正达到内存限制。实际上,我们已经从160万行增加到80万行,所以我们将数据集除以2,这不是数据库的总体增长,因为我们保留了旧表,我们能够在相同的条件下运行测试。如果这是正确的解释,那么第二个查询似乎使用了相同的键,如果不是,请添加正确的解释,使用武力时请添加解释。也许它更快,因为在运行索引的几秒钟内,索引就被缓冲了。请尝试在使用force的查询之后不使用force运行第一个查询。您的索引确实比表大,所以从硬盘加载可能需要一些时间。@Solarflare,实际上它是相同的索引名,但在两个不同的表上—旧表和新表。我们已经在一个脚本中运行了1000次查询,每次都要进行基准测试,以避免像您所说的那样使用索引缓冲/未缓冲。我们的DB机器是amazon RDS,具有16go的RAM和SSD。我将为force版本添加解释,感谢您的帮助:@Solarflare我已经添加了force版本的解释,并且我已经重命名了表和索引,因此它是clearerIt,因为您的数据增长了,它可能刚刚达到内存限制。实际上,我们已经从160万行增加到80万行,所以我们将数据集除以2,这不是数据库的总体增长,因为我们保留了旧表,我们能够在相同的条件下运行测试。如果这是正确的解释,那么第二个查询似乎使用了相同的键,如果不是,请添加正确的解释,使用武力时请添加解释。也许它更快,因为在运行索引的几秒钟内,索引就被缓冲了。请尝试在使用force的查询之后不使用force运行第一个查询。您的索引确实比表大,所以从硬盘加载可能需要一些时间。@Solarflare,实际上它是相同的索引名,但在两个不同的表上—旧表和新表。我们已经在一个脚本中运行了1000次查询,每次都要进行基准测试,以避免像您所说的那样使用索引缓冲/未缓冲。我们的DB机器是amazon RDS,具有16go的RAM和SSD。我将为force版本添加解释,感谢您的帮助:@Solarflare我已经添加了force版本的解释,并且我已经重命名了表和索引,以便更清晰