MySQL 8.0 新特性之函数索引

请讲解下,MySQL 8.0 新特性之函数索引
最新回答
给你一口甜甜

2026-10-21 13:17:17

MySQL 8.0引入的函数索引(Functional Index)是一项重要特性,允许基于表达式而非列值或前缀创建索引。以下是对该特性的详细解析:

一、核心功能
  1. 表达式索引支持将函数/表达式结果作为索引键,例如:

    CREATE TABLE t1 (col1 INT, INDEX ((ABS(col1)))); -- 对绝对值建索引CREATE INDEX idx ON t1 ((col1 + col2)); -- 对两列和建索引
  2. 混合索引可混合使用函数列和普通列:

    CREATE INDEX idx ON t1 (col1, (col2 * 2));
  3. 排序控制支持ASC/DESC排序选项:

    ALTER TABLE t1 ADD INDEX ((col1 * 40) DESC);
二、实现机制
  • 虚拟计算列函数索引通过隐藏的虚拟列实现,会占用表的总列数限制(参考Section C.10.4)。

  • 与计算列的关系遵循计算列的所有限制:

    禁止使用子查询、变量、存储函数等

    仅支持可计算列的函数(参考13.1.20.8和13.1.9.2节)

三、使用规范
  1. 语法要求

    表达式必须用双括号包裹:

    INDEX ((col1 + col2)) -- 正确INDEX (col1 + col2) -- 错误

    禁止纯列名函数索引:

    INDEX ((col1)) -- 错误,应使用普通索引INDEX (col1)
  2. 前缀限制

    不支持列前缀索引

    替代方案:使用SUBSTRING()或CAST()

四、特殊场景处理
  1. JSON数据索引需通过CAST转换数据类型并处理排序规则:

    -- 方案1:索引使用与JSON_UNQUOTE相同的排序规则CREATE INDEX idx ON employees ((CAST(data->>"$.name" AS CHAR(30)) COLLATE utf8mb4_bin));-- 方案2:查询使用完整CAST表达式SELECT * FROM employees WHERE CAST(data->>'$.name' AS CHAR(30)) = 'James';
  2. 外键限制外键约束不支持函数索引

五、注意事项
  1. 索引管理

    删除字段前需先删除依赖的函数索引

    重复函数索引不会报错(与普通索引不同)

  2. 性能考量

    复杂表达式可能增加计算开销

    优化器可能无法充分利用函数索引

  3. 存储限制

    函数索引使用虚拟列而非存储列

    主键不能包含函数列

六、典型应用场景
  1. 条件优化

    -- 为WHERE ABS(col) > 100条件创建索引CREATE INDEX idx ON table1 ((ABS(col)));
  2. 计算字段加速

    -- 加速JSON字段查询CREATE INDEX idx ON products ((CAST(data->>'$.price' AS DECIMAL(10,2))));
  3. 多列组合计算

    -- 为经纬度距离计算创建索引CREATE INDEX idx ON locations ((POW(lat-30, 2) + POW(lng-120, 2)));

函数索引通过表达式计算扩展了传统索引的能力,特别适合处理衍生数据、复杂条件查询等场景,但需注意其实现机制带来的限制和性能影响。