为什么MySQL停止“使用分组索引”,尽管这样做效率较低

为什么MySQL停止“使用分组索引”,尽管这样做效率较低,mysql,Mysql,该表由遗留应用程序使用,因此我们无法更改模式本身 我们有一张大约160万行的桌子 mysql> describe courses_old ; +---------------+------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------------+------------------+----

该表由遗留应用程序使用,因此我们无法更改模式本身

我们有一张大约160万行的桌子

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版本的解释,并且我已经重命名了表和索引,以便更清晰