You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何MySQL查询未使用name索引排序?强制使用也无效

WordPress wp_terms表查询索引失效问题分析

表结构

参考WordPress数据库设计,表创建语句如下:

CREATE TABLE wp_terms (
    term_id    bigint(20) unsigned auto_increment,
    name       varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci NOT NULL DEFAULT '',
    slug       varchar(200),
    term_group bigint(10) DEFAULT 0,

    PRIMARY KEY ( term_id )
) ENGINE=InnoDB;

索引信息

执行show index from wp_terms;得到以下结果:

MySQL> show index from wp_terms;
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| 表名     | 是否非唯一 | 索引名   | 索引中的序号 | 列名        | 排序规则   | 基数        | 子部分长度 | 压缩状态 | 可为空 | 索引类型   | 注释     | 索引注释       | 是否可见 | 表达式     |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| wp_terms |          1 | name     |            1 | name        | A         |      716638 |      191 |   NULL |      | BTREE      |         |               | YES     | NULL       |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+

执行的查询

执行查询语句select name from wp_terms order by name limit 1;,结果如下:

MySQL> select name from wp_terms order by name limit 1;
+--------------------+
| name               |
+--------------------+
|  ****************  |
+--------------------+
1 row in set (0.83 sec)

执行计划

执行explain查看查询计划:

MySQL> explain select name from wp_terms order by name limit 1;
+----+-------------+----------+------------+------+---------------+------+---------+------+--------+----------+----------------+
| id | 查询类型     | 表名     | 分区       | 访问类型 | 可能的索引     | 使用索引 | 索引长度 | 关联列 | 扫描行数 | 过滤比例   | 额外信息        |
+----+-------------+----------+------------+------+---------------+------+---------+------+--------+----------+----------------+
|  1 | SIMPLE      | wp_terms | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 802726 |   100.00 | Using filesort |
+----+-------------+----------+------------+------+---------------+------+---------+------+--------+----------+----------------+

问题原因分析

核心问题:name是前缀索引,无法支撑完整排序需求

从索引信息可以看到,name索引只取了字段前191个字符建立(Sub_part=191),属于前缀索引。MySQL的BTREE前缀索引仅能用于前缀匹配类查询,而order by name需要基于字段的完整字符序列排序——不同的name值可能前191个字符完全相同,但后续字符不同,前缀索引无法区分这些值的完整顺序,因此优化器不会将其列为possible_keys。

即使强制使用force index(name),优化器也会判断出该索引无法提供完整排序依据,最终仍会回退到全表扫描+文件排序,因为前缀索引里没有足够信息确定整个name字段的排序顺序,无法直接通过索引获取排序后的第一条数据。

解决方向

若要让索引支持该排序查询,需将name索引改为全字段索引,执行以下语句重建索引:

ALTER TABLE wp_terms DROP INDEX name;
ALTER TABLE wp_terms ADD INDEX name(name);

重建后优化器可利用全字段索引的有序性,直接通过索引快速定位排序后的第一条数据,避免全表扫描和文件排序。


内容的提问来源于stack exchange,提问作者Alex C

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 15:30:57