json_extract路径必须以$开头、数组下标从0开始、字段不存在时静默返回null;->返回带引号json值,->>去引号返回字符串;where中使用会导致全表扫描,应建生成列+索引优化。

直接用 JSON_EXTRACT 加路径表达式就能取,但数组下标从 0 开始、路径必须以 $ 开头、越界或字段不存在都静默返回 NULL —— 这三点最容易出错。
路径写法必须严格遵循 $ 开头 + 点号/方括号混用
MySQL 不认 /name 或 name 这种省略根符号的写法。嵌套数组路径要一层层展开,比如:
-
$.items[0].price→ 正确:取items数组第一个对象的price -
$.users[1].profile.name→ 正确:第二位用户(索引 1)的 profile 中 name 字段 -
$.data."user-id"→ 正确:键名含短横线时必须加双引号 -
items[0].price或/items/0/price→ 错误:不以$开头,一律返回NULL
-> 和 ->> 的区别直接影响结果类型
-> 是 JSON_EXTRACT 的语法糖,但返回带双引号的字符串;->> 才等价于 JSON_UNQUOTE(JSON_EXTRACT()),返回纯文本或数字字符串:
-
SELECT data -> '$.items[0].name' FROM t→ 得到"Alice" -
SELECT data ->> '$.items[0].name' FROM t→ 得到Alice(无引号) - 对布尔值如
true,->>返回"true",不是原生布尔类型 - 如果
data是NULL或 JSON 格式非法,两者都返回NULL
WHERE 条件里用 ->> 查嵌套数组字段会全表扫描
MySQL 对 JSON 字段路径查询无法走索引,每次执行类似 WHERE data ->> '$.items[0].status' = 'paid' 都要解析整列 JSON:
- 临时缓解:加
AND JSON_VALID(data)过滤掉非法 JSON,避免干扰 - 长期方案:建生成列 + 索引,例如:
ALTER TABLE t ADD COLUMN first_status VARCHAR(20) GENERATED ALWAYS AS (data ->> '$.items[0].status') STORED;<br>CREATE INDEX idx_first_status ON t(first_status);
-
STORED必须写,VIRTUAL列不能建索引
想把数组展开成多行?别硬写多个 [0][1][2]
手动拼一堆 JSON_EXTRACT(..., '$.items[0]') + UNION 不仅难维护,还容易漏元素。MySQL 8.0+ 推荐用 JSON_TABLE:
SELECT jt.id, jt.price FROM t, JSON_TABLE(t.data, '$.items[*]' COLUMNS (id INT PATH '$.id', price DECIMAL(10,2) PATH '$.price')) AS jt;-
[*]表示遍历所有数组项,比固定下标健壮得多 - 5.7 不支持
JSON_TABLE,只能靠应用层拆解或升级版本
真正卡住性能的不是写不对路径,而是把 JSON 字段放进 WHERE 或 JOIN 后没意识到它彻底放弃了索引能力;嵌套越深、数组越长,每次查询的解析开销就越不可控。











