首页/数据/SQL 速查/JSON 多值索引(8.0.17+)
性能与执行计划72 条

JSON 多值索引(8.0.17+)

为 JSON 数组的每个元素建立索引条目:让 MEMBER OF、JSON_CONTAINS 等条件可以走索引。

SQL 速查数据更新于 2026-10-13

多值索引是什么

多值索引是 MySQL 8.0.17 引入的特性:为 JSON 数组的每个元素各建一条索引记录,让「数组包含某值」这类判断也能走索引,而不是把整列展开之后再过滤。

基本信息

版本MySQL 8.0.17 起支持
语法在 CAST(表达式 AS 类型 ARRAY) 上建索引
元素类型CAST 目标类型要覆盖元素值域,可选 CHAR/SIGNED/UNSIGNED/DATE 等
可配合的条件MEMBER OF、JSON_CONTAINS、JSON_OVERLAPS 等
验证方式用 EXPLAIN 确认命中多值索引

典型使用场景

  • 商品标签数组的检索
  • 用户兴趣标签匹配
  • 订单里多商品 ID 的包含判断
  • JSON 数组字段高频过滤时替代展开查询
  • 评估是否值得把 JSON 拆成关联表

示例

示例
-- 在数组元素上建多值索引
ALTER TABLE products
  ADD INDEX idx_tags ((CAST(tags -> '$.tags' AS CHAR(20) ARRAY)));

-- 可命中多值索引的写法
SELECT * FROM products
WHERE JSON_CONTAINS(tags -> '$.tags', '"book"');

SELECT * FROM products
WHERE 'book' MEMBER OF (tags -> '$.tags');

-- 检查是否命中
EXPLAIN SELECT * FROM products
WHERE 'book' MEMBER OF (tags -> '$.tags');

条件与命中情况

条件写法能否用多值索引说明
MEMBER OF可以最直接的数组包含判断
JSON_CONTAINS可以表达式需与索引一致
JSON_OVERLAPS可以判断两个数组有交集
先展开再过滤不适用走的是展开后的行集
JSON 列等值比较不能整体比较用不上数组索引
CAST 的目标类型要与数据匹配:元素超长会被截断、类型不符会匹配异常,建索引前先核对元素实际取值范围与长度。
多值索引只解决「包含」类判断:要按数组元素分组统计或排序,仍需要展开成行,或考虑拆成关联表。
多值索引可以与普通索引共存:只给高频的包含判断建多值索引,其余 JSON 查询仍走生成列或表达式索引,两套方案并不冲突。
同一 JSON 路径上重复建多种索引要谨慎:索引越多写入维护越重,先明确查询形态,再决定用多值索引还是生成列索引。

易错点

  • CAST 类型与数据不匹配:元素超长或类型不符会导致截断或匹配异常,建索引前先核对数据
  • 改写后不验证命中:只有特定函数能利用多值索引,用 EXPLAIN 确认
  • 把多值索引当万能 JSON 索引:它只服务数组包含类判断,其他 JSON 查询仍需别的方案
  • 元素数量巨大:索引记录数随数组长度成倍增长,写入与体积成本要评估
  • 索引表达式与查询写法不一致:路径或字段名对不上就用不上索引

数据来源与参考

  • MySQL 8.0 Reference Manual · Multi-Valued Indexes
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌