当前位置:首页 > 文章列表 > 数据库 > MySQL > 部分更新 怎样减少 JSON 写放大

部分更新 怎样减少 JSON 写放大

来源:17golang原创 2026-10-25 10:58:51 0浏览 收藏

JSON 列里只改一个字段时,不要先在应用层读取整份文档、改完再把完整 JSON 写回去。更合适的做法是让 UPDATE 直接使用 JSON_SET()、JSON_REPLACE() 或 JSON_REMOVE(),并保证输入列和目标列是同一个 JSON 列。这样 MySQL 才有机会对二进制 JSON 做原地部分更新,减少存储层的写放大;如果使用行格式复制,再配合 binlog_row_value_options=PARTIAL_JSON,也可以减少副本日志中的 JSON after-image。

要点速览
  • JSON_SET() 既能替换已有路径,也能添加新路径;只替换已有值时可考虑 JSON_REPLACE()。
  • 部分更新的关键是“同一 JSON 列作为输入和目标”,直接赋整段字符串会退化为完整替换。
  • JSON_STORAGE_FREE() 可辅助判断列内是否出现可复用的空闲空间,但它不是性能基准。

先把整段回写改成路径更新

假设订单表的 attributes 是 JSON 列,现在只想把配送偏好改成 express。下面两种语句结果可能相同,但写入路径不同:

-- 只更新 attributes 中的 delivery.speed,输入列和目标列保持一致
UPDATE orders
SET attributes = JSON_SET(attributes, '$.delivery.speed', 'express')
WHERE id = 1001;

-- 只在路径已经存在时替换;路径不存在时不会新增字段
UPDATE orders
SET attributes = JSON_REPLACE(attributes, '$.delivery.speed', 'express')
WHERE id = 1001;

-- 删除一个路径,避免把剩余键重新拼成完整 JSON
UPDATE orders
SET attributes = JSON_REMOVE(attributes, '$.delivery.legacy_code')
WHERE id = 1001;

JSON_SET() 的路径和值按从左到右处理,因此一次语句里多个路径要注意前一个修改会成为后一个路径的输入。需要“字段不存在就不动”的语义时,用 JSON_REPLACE();需要删除字段时使用 JSON_REMOVE()。这些函数只解决 JSON 文档内部的局部修改,不会替你判断业务字段是否允许变更。

MySQL JSON_SET、JSON_REPLACE 和 JSON_REMOVE 从同一 attributes 列定位不同 JSON 路径的结构说明图
图1:JSON 路径更新结构说明图,展示同一 JSON 列与三个修改函数的静态关系,不是数据库截图或运行证据。

让 MySQL 保留原地部分更新条件

MySQL 官方文档给出的核心条件有三个:目标列确实声明为 JSON;更新表达式使用上述三个修改函数;输入列和目标列必须是同一列。例如 attributes = JSON_SET(attributes, ...) 满足这个方向,而把 profile 的内容计算后写入 attributes,即使结果只改变一个键,也不能按同样方式利用该优化。

因此,下面这种“从应用层带回完整文档再赋值”的写法不要作为局部更新方案:

-- 这是完整替换,不是 JSON 列的路径级部分更新
UPDATE orders
SET attributes = '{"delivery":{"speed":"express"},"coupon":"NEW"}'
WHERE id = 1001;

如果业务一次确实要重建整个文档,完整替换并不错误,只是不要把它误认为减少 JSON 写放大的路径。尤其是复杂数组的大范围重排、跨字段迁移或 schema 重建,局部函数不一定能带来同等收益。

用 JSON_STORAGE_FREE 做低成本检查

更新后可以查看 JSON 二进制表示中当前可复用的空闲空间。这个指标适合检查“是否可能发生了原地更新”,不适合直接当作吞吐量或延迟结论:

-- 查看这一行 JSON 文档的占用和可复用空间
SELECT
  JSON_STORAGE_SIZE(attributes) AS stored_bytes,
  JSON_STORAGE_FREE(attributes) AS free_bytes
FROM orders
WHERE id = 1001;

用 JSON_SET()、JSON_REPLACE() 或 JSON_REMOVE() 缩短某个值后,JSON_STORAGE_FREE() 可能变大;直接给 JSON 列赋新文档,或更新不能利用原地优化时,通常会看到 0。结果还会受到新值大小、列布局和更新表达式的影响,所以要在代表性数据上配合慢日志、I/O 与事务耗时观察。

MySQL JSON_STORAGE_SIZE 与 JSON_STORAGE_FREE 连接 JSON 列更新结果和二进制日志边界的结构说明图
图2:存储空间检查结构说明图,展示 JSON 列、占用空间、空闲空间与日志设置的关系,不是运行结果截图。

复制场景再处理二进制日志写放大

存储层的部分更新和复制日志不是一回事。MySQL 8.4 中,行格式复制默认仍可能把 JSON 完整文档写入 after-image;可以在确认副本版本和运维流程支持后设置:

-- 仅对当前会话启用,先在灰度链路观察副本应用情况
SET SESSION binlog_row_value_options = 'PARTIAL_JSON';

-- 生产环境通常由运维配置持久化,而不是把全局变更写进业务事务
-- SET GLOBAL binlog_row_value_options = 'PARTIAL_JSON';

官方说明中,PARTIAL_JSON 只影响行格式日志中 JSON 修改部分的记录方式;如果服务端无法生成部分更新,仍会使用完整文档。语句格式复制对 JSON 部分更新有自己的记录规则,因此不要只看一个会话变量就推断所有链路都变小。

常见问题

JSON_SET 和 JSON_REPLACE 怎么选?

希望路径不存在时自动新增,用 JSON_SET();只允许替换已有路径,用 JSON_REPLACE(),这样能避免拼写错误悄悄创建新键。

JSON_STORAGE_FREE 返回 0 就代表没有更新成功吗?

不代表。它只表示当前没有可报告的空闲空间;更新可能成功,但新值更大、表达式不满足原地条件,或旧空间被重新利用后没有剩余空洞。

把整个 JSON 文档放进变量再 JSON_SET 还算部分更新吗?

对用户变量而言,值会被完整替换;要让列级部分更新生效,应直接在 UPDATE 中以目标 JSON 列作为 JSON_SET() 的输入。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
EXPLAIN FORMAT=JSON 怎样读取窗口节点EXPLAIN FORMAT=JSON 怎样读取窗口节点
上一篇
EXPLAIN FORMAT=JSON 怎样读取窗口节点
空间索引 怎样配合 GeoJSON 查询
下一篇
空间索引 怎样配合 GeoJSON 查询
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    683次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    699次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    748次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    714次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    551次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码