MySQL 5.7 的 JSON 列无法直接建 B+ 树索引,WHERE 中使用 JSON_EXTRACT()、-> 或 ->> 均触发全表扫描;需通过 STORED 生成列配合 CAST 或 ->> 确保类型匹配,且路径必须字面量固定。

因为 MySQL 5.7 的 JSON 列本身不能建 B+ 树索引,所有基于 JSON_EXTRACT()、-> 或 ->> 的 WHERE 条件都会触发全表扫描——这不是写法问题,是存储引擎层的硬限制。
为什么直接 WHERE JSON_EXTRACT() 永远走不了索引
MySQL 优化器无法把运行时计算的表达式(比如 JSON_EXTRACT(data, '$.status'))映射到已有索引上。即使你在 data 字段上建了普通索引,EXPLAIN 里也只会显示 type: ALL 和 key: NULL。本质原因是:JSON 类型在 InnoDB 中以二进制格式存储,不是字符串,函数包装后无法做前缀匹配或等值查找。
- 哪怕只有 1 万行,响应时间也会明显抖动;超过 10 万行,基本不可用于线上高频查询
-
JSON_CONTAINS()、JSON_SEARCH()同样不走索引,除非操作对象是已索引的生成列 - MySQL 8.0.13+ 才支持函数索引(
CREATE INDEX ... ON (json_col->>'$.field')),5.7 没这个能力
必须用 STORED 而不是 VIRTUAL 生成列
很多人试过 VIRTUAL 列加索引,结果报错 ERROR 3107 (HY000): Generated column can only be stored。这是因为 InnoDB 在 5.7 中禁止对 VIRTUAL 列创建二级索引——它只存元数据,B+ 树需要真实值来构建。
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
-
STORED列在 INSERT/UPDATE 时就计算并落盘,索引直接建在这份确定值上 - 虽然多占一点磁盘,但避免了每次查都要解析 JSON + 计算路径的开销
- 表达式必须是确定性的:不能含
NOW()、RAND()、子查询,否则 DDL 失败
类型不匹配是最隐蔽的坑
写 AS (JSON_EXTRACT(data, '$.user_id')) 看着没问题,但返回的是带双引号的 JSON 字符串 "123",不是整数 123。如果你的查询是 WHERE user_id = 123,而生成列类型是 VARCHAR,就会发生隐式转换,索引失效。
- 数值字段务必套
CAST(... AS UNSIGNED)或用->>(自动去引号) - 字符串字段推荐用
data->>'$.name',而不是JSON_EXTRACT(data, '$.name') - 路径必须字面量固定:
'$.items[0].id'可以,CONCAT('$.', @key)不行
真正麻烦的不是加索引这一步,而是路径一旦固化在 STORED 列里,后期想查 $.items[1].id 就得新增一列;如果业务路径经常变,不如早期就拆成关系表,别硬扛 JSON 查询。

















