mysql 8.0 的 json_extract 更快源于解析器重写,实测快15%–35%,但需满足 strict_mode=on、json列not null、路径无通配符;不建索引时版本差异几乎不可测,函数索引和 collation 一致性才是性能关键。

MySQL 8.0 的 JSON_EXTRACT 本身确实更快,但“快”只在特定条件下成立——多数人没配对参数或没建索引,实际查起来和 5.7 几乎没差别。
JSON_EXTRACT 在 8.0 里为什么变快了
核心是解析器重写:8.0 用原生 JSON parser 替代了 5.7 依赖的 Boost.PropertyTree,减少了内存拷贝和中间对象构造。实测平均快 15%–35%,但这个提升只体现在单次函数调用开销上。
- 前提一:
innodb_strict_mode=ON(8.0 默认开启,5.7 默认关)——校验前置,避免运行时反复解析失败回退 - 前提二:JSON 字段定义为
NOT NULL——5.7 对 NULL 值有额外空值检查,8.0 已优化该路径 - 前提三:路径表达式不含通配符(如
$[*].id)——5.7 不支持数组展开,会全量解析整个 JSON;8.0 支持且做了短路匹配,此时差距可达 3×
不建索引时,版本差异几乎不可测
哪怕 JSON_EXTRACT 快了 30%,只要查询写成 WHERE JSON_EXTRACT(data, '$.status') = 'active' 且 data 没索引,MySQL 就得对每行执行完整解析 + 字符串比较——瓶颈在 I/O 和解析逻辑,不在函数实现。
- 5.7 只能靠
STORED生成列 + 索引,写入时多一次计算和存储,空间和写性能有代价 - 8.0 支持函数索引:
CREATE INDEX idx_status ON t ( (JSON_EXTRACT(data, '$.status')) ),无需冗余字段,索引直接建在表达式上 - 注意:函数索引要求表达式确定性,
JSON_EXTRACT()符合,但NOW()或RAND()不行
字符集与排序规则会影响结果一致性
JSON_EXTRACT 返回的是 JSON 类型值,比较时隐式转字符串。而 5.7 常用 utf8mb4_general_ci(大小写不敏感),8.0 默认 utf8mb4_0900_as_cs(大小写敏感)。
- 语句
JSON_EXTRACT(data, '$.Name') = '"admin"'在 5.7 可能命中{"name": "admin"},但在 8.0 默认不命中 - 这不是 bug,是 collation 行为差异;误判为“8.0 结果不对”,常导致性能测试失真
- 建议显式加
COLLATE utf8mb4_bin统一行为,例如:JSON_EXTRACT(data, '$.Name') COLLATE utf8mb4_bin = '"admin"'
真正卡慢的从来不是函数,而是你没把 JSON 当字段对待
很多人盯着 JSON_EXTRACT 的毫秒级差异,却忽略一个事实:JSON 字段一旦参与 WHERE、ORDER BY 或 JOIN 条件,就必须考虑索引策略。8.0 的函数索引、部分更新、JSON_TABLE 等能力,本质是让 JSON 从“文档附件”变成“可分析的一等公民”。没用上这些,光换版本,只是把慢操作从应用层挪到了数据库层而已。











