mysql 5.7 不支持函数索引和降序索引的物理实现,8.0+ 才真正支持表达式索引(自动映射为虚拟列+b+树)和叶子节点级降序排序,且要求查询与索引定义字面完全一致。

MySQL 5.7 和 MySQL 8.0 的索引算法差异,根本不在“B-Tree vs 倒排索引”这个层面——InnoDB 的主键和二级索引在两个版本中都基于 B+ 树(B-Tree 的变种),且 MySQL 官方至今未在 InnoDB 中引入倒排索引(如 Elasticsearch 那类)。所谓“差异”,其实是 B+ 树如何组织、优化器能否识别、以及索引定义能力是否扩展 的演进。
CREATE INDEX 语法解析失败:5.7 不认函数表达式
- 常见错误现象:
ERROR 1064 (42000): You have an error in your SQL syntax - 这不是配置或字符集问题,是 5.7 的 SQL 解析器压根不支持括号内写函数,比如
CREATE INDEX idx ON t ((UPPER(name))) - 8.0.13+ 才真正把
(UPPER(name))当作一个合法的“表达式索引项”来解析,此前所有带函数的建索引语句都会卡在语法分析阶段 - 如果你用 ORM 自动生成 DDL 或复用旧脚本,在 5.7 上跑 8.0 的建索引语句,第一反应往往是“SQL 写错了”,其实只是版本越界
函数索引 ≠ 倒排索引,但依赖虚拟列实现
- MySQL 8.0 的函数索引本质是:自动创建不可见虚拟生成列 + 对该列建普通 B+ 树索引
- 所以它仍受限于 B+ 树特性:适合等值查询、左前缀范围扫描;对
UPPER(name) LIKE '%abc%'无效,对UPPER(name) = 'ABC'有效 - 它不改变底层存储结构,也不引入新索引类型,只是让优化器能在 WHERE 子句中匹配到完全一致的函数调用
- 你执行
SHOW CREATE TABLE t后看不到显式的虚拟列名,但能看到索引定义里保留着(UPPER(name)),说明它被当作表达式持久化了,不是临时计算
降序索引从“语法糖”变成“物理有序”
- 在 5.7 中写
INDEX (a DESC, b ASC),SHOW CREATE TABLE会悄悄抹掉DESC,实际建出来仍是(a ASC, b ASC) - 8.0 真正支持 B+ 树叶子节点按指定方向物理排序,所以
ORDER BY a DESC, b ASC可免Using filesort,前提是 WHERE 条件覆盖最左前缀(如WHERE a > 100) - 注意:如果查询是
ORDER BY a DESC, b DESC,而索引定义是(a DESC, b ASC),依然不命中——方向必须严格一致
真正容易被忽略的一点:函数索引和降序索引都要求查询中的表达式/排序方向与索引定义字面完全一致,连空格、括号嵌套层级都不能差。这不是模糊匹配,是编译期绑定。











