mysql 5.7 不支持函数索引,8.0 才真正可用;5.7 中带函数的 create index 会报 error 1064,而 8.0.13+ 支持双括号语法如 create index idx on t ((upper(name))),且要求函数必须确定性。

MySQL 5.7 不支持函数索引,8.0 才真正可用
MySQL 5.7 的 CREATE INDEX 语法不识别表达式,任何带函数的索引定义都会直接报错。比如你想对 UPPER(name) 建索引,5.7 会拒绝执行;而 8.0 允许写成 CREATE INDEX idx_name_upper ON t1 ((UPPER(name)))(注意双括号语法)。这背后是优化器能真正“理解”表达式结果的稳定性,并在 WHERE UPPER(name) = 'ABC' 这类查询中命中索引。
常见错误现象:ERROR 1064 (42000): You have an error in your SQL syntax —— 很可能是在 5.7 上误用了函数索引语法。
- 必须用 MySQL 8.0.13 或更高版本,低版本 8.0(如 8.0.1)不支持
- 函数必须是确定性的(deterministic),例如
UPPER()、JSON_EXTRACT()可以,NOW()、RAND()不行 - 索引列不能包含子查询或用户变量
- 建完后用
SHOW CREATE TABLE t1能看到表达式被原样保留,不是展开为虚拟列
不可见索引在 8.0 中可开关,5.7 完全没有该概念
不可见索引(INVISIBLE)不是删除,也不是注释掉,而是让优化器“假装看不见”——它依然占用空间、仍会被 INSERT/UPDATE 维护,但不会被 EXPLAIN 选中,也不会影响 ANALYZE TABLE 的统计信息。这是灰度下线索引最安全的方式。
5.7 没有 INVISIBLE 关键字,加了会报语法错误;而 8.0 支持两种创建方式:
- 建表时指定:
KEY idx_c1 (c1) INVISIBLE - 已有索引修改:
ALTER TABLE t1 ALTER INDEX idx_c1 INVISIBLE或VISIBLE
容易踩的坑:不可见索引仍会拖慢写入性能,因为它照常更新;另外,mysqldump 默认导出时会带上 INVISIBLE 属性,若目标库是 5.7,恢复会失败。
降序索引从“语法允许但无效”变成“真生效”
MySQL 5.7 允许你在 CREATE INDEX 里写 DESC,比如 KEY idx_c1_c2 (c1, c2 DESC),但 SHOW CREATE TABLE 会发现 DESC 被悄悄抹掉了,且 ORDER BY c1 ASC, c2 DESC 仍会触发 Using filesort。本质上,5.7 的 B+ 树只按升序组织,降序只是语法糖。
MySQL 8.0 真正实现了物理层面的降序存储,B+ 树叶子节点可按指定方向排序。效果立竿见影:
-
EXPLAIN显示Extra: Using index,不再有Using filesort - 混合排序如
ORDER BY c1 DESC, c2 ASC也能利用索引(前提是索引定义匹配) - 注意:只有 InnoDB 支持,MyISAM 不行
- 如果升级后发现旧索引没自动转为降序,得手动重建:
ALTER TABLE t1 DROP INDEX idx_c1_c2, ADD INDEX idx_c1_c2 (c1, c2 DESC)
哈希索引仅限于 MEMORY 引擎,InnoDB 的“哈希索引”仍是自适应的
别被宣传误导:MySQL 8.0 并没有给 InnoDB 加上用户可定义的哈希索引。所谓“哈希索引支持”,仅指 MEMORY 表现在支持 HASH 类型索引(5.7 也支持)。InnoDB 的自适应哈希索引(AHI)仍是后台自动构建的、只针对等值查询的内存加速结构,用户无法控制或显式创建。
真正变化在于 AHI 的管理逻辑更激进:8.0 默认开启 innodb_adaptive_hash_index,且引入了分区锁减少争用;而 5.7 在高并发下 AHI 更容易成为瓶颈。
如果你在 EXPLAIN 里看到 type: index_merge 或反复出现 Using where; Using index 却性能差,先确认是不是误以为 InnoDB 支持了哈希索引——实际还是 B+ 树,优化方向仍是覆盖索引或调整联合索引顺序。











