json解析性能问题主因是同步阻塞、重复解析与全表扫描;应拆分逻辑、加缓存,并在sql server中用openjson(with...)、mysql中用变量暂存、postgresql中用jsonb+gin索引,且必须显式校验与记录错误。

触发器里直接解析 JSON 并入库,90% 的性能问题出在同步阻塞 + 重复解析 + 全表扫描三连击。别硬扛,该拆就拆,该缓存就缓存。
SQL Server 触发器中用 OPENJSON 必须加 WITH 子句
直接 OPENJSON(@json) 返回的是带 key、value、type 的通用三列结果,没法直接 INSERT 到目标表。不定义结构,后续还得再 CASE WHEN type = 2 THEN CAST(value AS INT) 转类型,既慢又易错。
实操建议:
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
- 始终搭配
WITH显式声明字段名、类型和路径,比如WITH (user_id INT '$.user.id', event_time DATETIME2 '$.ts') - 路径中字段含空格或特殊字符时,必须用双引号包裹:
"click-type"→'$.["click-type"]' - 如果 JSON 可能缺失某字段,
WITH中对应列会自动为NULL,不用额外ISNULL包裹 - 避免在
WITH中写复杂表达式(如CONVERT(DATE, $.ts)),先提取原始值,再在外层转换
MySQL 触发器里别反复调用 JSON_EXTRACT
在 BEFORE INSERT 触发器中写 SET NEW.user_name = JSON_EXTRACT(NEW.payload, '$.user.name'); 看似干净,但如果同一字段被引用 3 次,数据库就解析 3 遍 JSON——尤其当 payload 是几 KB 的嵌套结构时,开销陡增。
实操建议:
- 用局部变量暂存解析结果:
SET @name := JSON_UNQUOTE(JSON_EXTRACT(NEW.payload, '$.user.name'));,后续全用@name - 提前用
JSON_VALID(NEW.payload)做校验,无效 JSON 直接SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Invalid JSON';终止,避免后续函数报错中断流程 - 对数组字段,优先用
JSON_LENGTH()判断长度,再决定是否走JSON_TABLE;空数组或单元素场景可绕过展开逻辑
PostgreSQL 触发器中 jsonb 比 json 快,但索引得配对建
json 类型每次查询都重新解析文本,jsonb 是二进制预解析格式,提取 ->> 或更新 jsonb_set() 快 3–5 倍。但如果你只在触发器里读,却没给常用路径建 GIN 索引,那跟没换一样。
实操建议:
- 存储字段必须用
jsonb,别用json;触发器内一律用NEW.payload ->> 'user.id'(返回文本)或NEW.payload -> 'user'(返回 jsonb 对象) - 高频查询路径必须建 GIN 索引:
CREATE INDEX idx_payload_user_id ON events USING GIN ((payload -> 'user' ->> 'id')); - 别在触发器里用
jsonb_array_elements()展开大数组——它生成多行结果,触发器无法直接 INSERT 多行;应改用jsonb_path_query_array()提前聚合,或交由外部任务处理 - 若需提取深层嵌套字段(如
$.data.items[0].price),用jsonb_path_query_first()比链式->->>更安全,自动处理空数组/缺失键
所有数据库:触发器中 JSON 解析失败必须显式拦截
MySQL 的 JSON_EXTRACT 遇到非法路径返回 NULL,PostgreSQL 的 ->> 同样静默返回 NULL,SQL Server 的 JSON_VALUE 在路径不存在时也返回 NULL。这些 NULL 往往变成目标表的默认值或约束冲突,最后查日志才发现是 JSON 结构变了。
实操建议:
- 关键字段提取后立刻校验:
IF @user_id IS NULL OR @user_id - SQL Server 中用
ISJSON(@json) = 0或JSON_VALUE(@json, '$.user.id') IS NULL做双重判断 - PostgreSQL 中结合
jsonb_typeof()防错:jsonb_typeof(NEW.payload -> 'user') != 'object'就跳过后续解析 - 日志表字段留一列
parse_error TEXT,把失败的 JSON 片段和错误原因写进去,别只靠RAISE EXCEPTION打断流程
最常被忽略的一点:触发器执行是行级的,哪怕你一次 INSERT 1000 行 JSON,OPENJSON 或 jsonb_path_query 就会被调用 1000 次。批量解析的收益,永远大于单行触发器里的任何优化。真要保实时,宁可用 CDC + 函数计算,也别在触发器里硬刚 JSON。










