key为null说明json查询未走索引;常见原因包括mysql版本过低不支持函数索引、虚拟列类型(virtual/stored)与索引不匹配、json路径表达式语法不一致(->与json_extract混用)等。

EXPLAIN SELECT 里 key 为 NULL,说明 JSON 查询没走索引
Navicat 17 的可视化执行计划本身不判断索引是否生效,它只是渲染 MySQL 返回的 EXPLAIN 结果。真正决定有没有用上索引的,是 EXPLAIN 输出中 key 列的值:如果为 NULL,基本可以断定没走索引。
常见原因包括:
- MySQL 版本低于 8.0.22,却直接对
json_extract(params, '$.item_id')建了函数索引(老版本不支持,必须用虚拟列) - 虚拟列定义用了
VIRTUAL类型,但索引建在了STORED列上(或反过来),类型不匹配导致优化器忽略 - WHERE 条件写的是
params->'$.item_id' = 123,但虚拟列表达式写的是json_extract(params, '$.item_id')—— 二者语法等价但内部 token 不同,MySQL 8.0.22 前不视为可复用 - 查询里混用了
->和JSON_EXTRACT(),优化器无法统一路径推导
在 Navicat 表设计器里建 JSON 虚拟列索引的实操要点
别依赖“自动识别 JSON 路径”——Navicat 不会帮你猜字段。你得手动建一列,再建索引,顺序不能错。
操作步骤:
- 右键表 → “设计表”,新增字段,名称建议与路径一致,如
item_id_virtual - 类型选
INT(或对应实际类型),勾选“虚拟”,虚拟类型选VIRTUAL(不是STORED,除非你要导出或备份该值) - 表达式填
json_extract(`params`, '$.item_id'),注意反引号包裹字段名,单引号包裹 JSON 路径 - 保存后,再右键该列 → “修改索引”,新建普通索引(不要选全文或空间索引)
- 确认
SHOW INDEXES FROM temp_record中能看到该虚拟列名出现在Column_name列,且Key_name非PRIMARY
Navicat 17 执行计划导出后,不能靠 Excel 对比 rows 值来判断性能退化
导出的 CSV 里 rows 是估算值,受统计信息、缓存、采样率影响极大。同一语句两次导出,rows 差 5 倍,不代表 SQL 变慢了。
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
真正可比的只有几个硬指标:
-
type是否从ref退化成ALL(全表扫描) -
key是否从索引名变成NULL(索引失效) -
Extra是否出现Using filesort或Using temporary(隐含排序/临时表开销) - 若用
EXPLAIN FORMAT=JSON手动执行,看query_cost字段(Navicat 17 支持该格式渲染,但需在「首选项 → 查询」中关闭Use legacy explain format)
为什么 Navicat 查询分析器里看不到 JSON 查询的真实耗时
Navicat 的“查询分析器”页面只展示 MySQL 慢查询日志或 performance_schema 的聚合结果,而 JSON 解析的 CPU 时间默认不计入慢查询阈值——MySQL 认为那是“计算开销”,不是“查询延迟”。
要捕获真实瓶颈,得绕过 Navicat UI:
- 在 MySQL 配置中启用
log_queries_not_using_indexes = ON,强制记录未走索引的 JSON 查询 - 执行
SELECT * FROM performance_schema.events_statements_history_long WHERE sql_text LIKE '%params->%',查timer_wait(单位纳秒) - 对比
timer_wait和lock_time + rows_examined × 10000(粗略估算 IO 开销),差值大就说明 JSON 解析本身吃 CPU
嵌套超过 3 层的 JSON 路径(比如 data.items[0].details.meta.tags[1]),Navicat 编辑器自身可能在语法高亮阶段卡住——这不是数据库问题,是客户端正则引擎崩溃,换用纯文本编辑器写语句再粘贴进去更稳。










