一直在SQL Server里折腾关系型数据的朋友,可能对JSON这玩意儿又爱又恨。爱的是它灵活,字段随便加,嵌套随便搞;恨的是真到查询、修改、跟应用联调的时候,总觉得隔着层纱。第26章我们专门聊SQL Server里的JSON,把它的函数、用法、坑全部摊开讲一遍。
这篇文章适合这么几类人:一是手上正好有JSON数据存在SQL Server里,但不知道怎么高效查询的;二是做接口开发,需要把表结构转成JSON返回给前端的;三是在传统关系型项目里想引入一点“半结构化”设计,但担心后续维护成本的架构师。不管你是哪一类,这篇都能给你一些可以直接抄作业的方案。
先说个结论:SQL Server对JSON的支持从2016版本开始正式加入,到2022版本已经非常成熟了。它不是像MongoDB那样把JSON当一等公民存,而是把JSON当作字符串存在表里,再通过一组内置函数做解析、查询、修改。这种方式的好处是兼容关系型生态,坏处是没搞明白这些函数之前,你会觉得查JSON比查普通表麻烦十倍。这篇文章就是把麻烦的部分拆开揉碎。
1. 整体设计思路:SQL Server凭什么敢碰JSON
1.1 为什么要在SQL Server里用JSON,而不是换数据库
先说一个核心问题:既然JSON是非结构化的东西,为什么不用专门的NoSQL数据库,非要在SQL Server里凑热闹。答案很简单:现实项目里不存在“全有或全无”的数据,更多时候是结构化数据占大头,偶尔夹着几块爱变的字段。
举个例子,你做一个订单系统,订单主体字段非常固定,订单号、客户ID、金额、状态,这些放到关系表里天经地义。但订单里还可能包含收货地址、发票信息、买家备注、优惠明细,这些东西不同渠道来的格式不一样,而且时常有调整。你要真为每个渠道建一张表,那就是自找麻烦。把这种“扩展字段”统一塞进一个JSON列里,既保留了随时变化的灵活性,又不影响主表的主流程查询,这才是合理的折中方案。
SQL Server 2016之后所有版本都支持JSON相关函数,包括2016、2017、2019、2022。SQL Server 2025(也就是最新的那个版本)甚至开始引入原生的JSON数据类型,不过那是后话,我们日常大多数项目还在2022或2019上,所以基于通用函数来聊最稳妥。
1.2 SQL Server里的JSON和普通字符串的区别
很多人会疑惑:JSON列不就是个varchar吗,有什么特殊的?物理存储上确实区别不大,SQL Server没有专门的JSON列类型(除非你用2025新特性),它就是用nvarchar(max)存着。但逻辑上有两个关键差别:
第一个差别是函数支持。你可以在T-SQL里调用JSON_VALUE、JSON_QUERY、OPENJSON这些函数,它们能够实时解析字符串里的JSON结构,提取标量值、查询数组、遍历对象,这种能力是普通字符串操作函数完全做不到的。
第二个差别是校验辅助。SQL Server提供了ISJSON函数,可以在写入时校验JSON格式是否正确,避免垃圾数据混进来。同时也可以在CHECK约束里用ISJSON=1来强制要求某列必须是合法JSON。
所以本质上,SQL Server处理JSON的思路是:存储用字符串,计算用专用函数。理解了这个设计哲学,后面所有函数就都好理解了。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 从JSON里取数据:JSON_VALUE、JSON_QUERY与JSON路径
2.1 JSON路径表达式:先搞懂这个,后面全通
SQL Server的JSON函数都依赖一个叫“JSON路径”的东西。路径表达式规定了你要从JSON的哪个位置取数据。它的语法非常有规律,记住几个符号就够用:
$表示JSON文本的根节点.后面跟对象属性名,比如$.name[n]表示数组下标,从0开始,比如$.items[0]- 可以用
.*或者[*]表示通配,遍历所有属性和数组元素
路径支持lax和strict两种模式。lax是默认模式,意思是路径匹配不到就返回NULL,不会报错;strict模式下匹配不到直接抛错。实际用下来,99%的场景用lax就够了,因为NULL可以正常处理,而抛错往往意味着要写更多错误处理逻辑。
举个例子,假设有这么一条JSON:
json复制{
"orderId": 10086,
"customer": {
"name": "张三",
"phone": "13800138000"
},
"items": [
{"sku": "A001", "qty": 2, "price": 19.9},
{"sku": "A002", "qty": 1, "price": 99.0}
],
"tags": ["加急", "企业客户"]
}
那么:
$.orderId取到10086$.customer.name取到张三$.items[0].sku取到A001$.tags[1]取到企业客户
这些路径表达式看起来挺简单,但很多人栽在细节上:属性名带空格或特殊符号、属性名是数字开头、数组嵌套多层。后面会专门讲。
2.2 JSON_VALUE:提取标量值
JSON_VALUE用于从JSON文本中提取一个标量值,返回值是一个字符串(或根据目标类型的隐式转换为数字、日期等)。它的语法是:
sql复制JSON_VALUE(expression, path)
注意路径前面没有$符开头的相对路径在SQL Server里是不认的,必须写完整路径,虽然相对路径在其他JSON工具里很常见,但在SQL Server这里必须从根节点开始。
实操示例,从上面那条JSON里取客户名和第一个商品的SKU:
sql复制DECLARE @json NVARCHAR(MAX) = N'{
"orderId": 10086,
"customer": {"name": "张三", "phone": "13800138000"},
"items": [
{"sku": "A001", "qty": 2, "price": 19.9},
{"sku": "A002", "qty": 1, "price": 99.0}
],
"tags": ["加急", "企业客户"]
}';
SELECT
JSON_VALUE(@json, '$.orderId') AS order_id,
JSON_VALUE(@json, '$.customer.name') AS customer_name,
JSON_VALUE(@json, '$.items[0].sku') AS first_sku,
JSON_VALUE(@json, '$.tags[1]') AS second_tag;
这里有几个细节要提醒:
一是JSON_VALUE只能取标量值,如果路径指向的是一个对象或数组,它返回NULL。很多人在这里踩坑,明明路径写对了,但结果就是NULL,原因就是目标位置不是标量。想取对象或数组,得用JSON_QUERY。
二是返回的标量值类型是nvarchar,如果后续要参与数值计算,记得加CAST或CONVERT。比如上面例子里的price,JSON_VALUE取出来是字符串'19.9',你需要CAST(JSON_VALUE(@json, '$.items[0].price') AS DECIMAL(10,2))才能做运算。
三是路径里的属性名是大小写不敏感的,SQL Server默认排序规则下$.Customer.Name和$.customer.name等价,这点和JavaScript对象访问不太一样,别被搞混。
2.3 JSON_QUERY:提取对象和数组
JSON_QUERY和JSON_VALUE是一对,它专门用于提取JSON对象或数组,返回的仍然是一段JSON文本(字符串形式)。如果路径指向的是标量值,JSON_QUERY返回NULL。
沿用上面的例子,想取出整个items数组:
sql复制SELECT
JSON_QUERY(@json, '$.items') AS items_array,
JSON_QUERY(@json, '$.customer') AS customer_object;
结果分别返回:
json复制[{"sku":"A001","qty":2,"price":19.9},{"sku":"A002","qty":1,"price":99.0}]
和
json复制{"name":"张三","phone":"13800138000"}
一个常用场景是把JSON里嵌的某个对象直接传给应用层,省得再拼字符串。举个例子,Web API返回订单信息,同时需要把客户信息作为一个嵌套对象返回,你就可以直接用JSON_QUERY把customer字段原样取出来,然后在FOR JSON里嵌回去。
这里有个非常容易犯的错:JSON_VALUE和JSON_QUERY用混。SQL Server官方文档也专门强调过这个差异。记住一句话:取叶子节点用JSON_VALUE,取分支节点用JSON_QUERY。叶子节点就是JSON树最末端的值,分支节点是还能再继续拆的对象或数组。
2.4 OPENJSON:把JSON变成一张表
如果说JSON_VALUE和JSON_QUERY是点状取值,那OPENJSON就是面状取数。它能把一段JSON数组或对象展开成一张关系表,这样就能和普通的表做JOIN、WHERE、GROUP BY,这是SQL Server JSON功能里最强大、也最值得深入掌握的函数。
OPENJSON有两种用法:
第一种是只传JSON文本,不指定schema,它会返回三列:key、value、type。type是表示值类型的数字:0表示null,1表示字符串,2表示数字,3表示布尔值,4表示数组,5表示对象。这种用法适合做调试,看JSON的整体结构。
sql复制SELECT * FROM OPENJSON(@json, '$.items');
此时返回每一行对应数组里的一个元素,key是数组索引字符串,value是元素对象的JSON文本。
第二种用法是指定WITH子句,把JSON里的字段映射到列。这是最常用的方式:
sql复制DECLARE @json NVARCHAR(MAX) = N'{
"orderId": 10086,
"items": [
{"sku": "A001", "qty": 2, "price": 19.9},
{"sku": "A002", "qty": 1, "price": 99.0}
]
}';
SELECT *
FROM OPENJSON(@json, '$.items')
WITH (
sku NVARCHAR(50) '$.sku',
qty INT '$.qty',
price DECIMAL(10,2) '$.price'
);
输出两行,分别是A001那条和A002那条,字段也都被转换成了对应的SQL类型。注意WITH子句里的路径是相对路径,不需要以$开头,它相对于OPENJSON第二个参数指定的位置。这个细节很多人搞错,写成'$.sku'也没事,但根节点不同,建议按官方惯例写相对路径,逻辑更清晰。
OPENJSON配合CROSS APPLY能实现非常灵活的行转列操作。比如订单表orders里有一列json_data,存的是商品明细数组,你想把所有订单的商品明细拍平,统计每个SKU卖了多少件,可以这么写:
sql复制SELECT
o.order_id,
item.sku,
item.qty,
item.price
FROM orders AS o
CROSS APPLY OPENJSON(o.json_data, '$.items')
WITH (
sku NVARCHAR(50) '$.sku',
qty INT '$.qty',
price DECIMAL(10,2) '$.price'
) AS item;
这种写法就跟查普通表没什么区别了,可以继续加WHERE、GROUP BY、ORDER BY。我实际做报表的时候,这种把JSON展开成行的操作几乎每周都要用到。
3. 结构化数据变JSON:FOR JSON的正确打开方式
3.1 FOR JSON PATH和FOR JSON AUTO的区别
需求和上一步相反:应用前端希望接口直接返回JSON,不想在代码层手动拼接。SQL Server提供了FOR JSON子句,直接把查询结果转成JSON文本。
FOR JSON有两种模式:
- FOR JSON AUTO:根据SELECT列表和表之间的JOIN关系自动决定JSON嵌套结构
- FOR JSON PATH:通过列别名里的点号
.手动控制嵌套层次
实践经验是:AUTO看起来很省事,但实际项目中用PATH的居多。原因很简单,PATH对输出结构有完全控制权,而AUTO在某些复杂JOIN场景下生成的嵌套结构不是我们想要的,还得回头调整SQL。
FOR JSON PATH的基本写法:
sql复制SELECT
order_id AS 'order.id',
customer_name AS 'order.customer.name',
sku AS 'items[0].sku'
FROM ...
FOR JSON PATH;
列别名里的点号会生成嵌套对象,items[0]语法生成数组元素。想生成JSON数组,用PATH模式的经典技巧是把重复的列名前缀设为同一个数组名,但注意PATH模式默认情况下不会自动合并数组,每个行的items键会出现多次,需要配合其它写法处理。
更推荐的方案是嵌套子查询,这样能够精确地生成数组:
sql复制SELECT
o.order_id,
o.customer_name,
(
SELECT
i.sku,
i.qty
FROM order_items AS i
WHERE i.order_id = o.order_id
FOR JSON PATH
) AS items
FROM orders AS o
WHERE o.order_id = 10086
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER;
这段SQL会生成类似这样的JSON:
json复制{
"order_id": 10086,
"customer_name": "张三",
"items": [
{"sku": "A001", "qty": 2},
{"sku": "A002", "qty": 1}
]
}
注意几个关键细节:
- 内层FOR JSON PATH前不需要写WITHOUT_ARRAY_WRAPPER,否则生成的是对象而不是数组
- 外层FOR JSON PATH默认返回一个数组(每个查询行一个元素),如果想返回单个对象,加
WITHOUT_ARRAY_WRAPPER - 生成的JSON默认是NVARCHAR(MAX)类型,可以直接赋值给变量
3.2 应对NULL值:怎么让字段不出现在JSON里
FOR JSON默认情况下,NULL值字段照样输出,变成"field": null。但在实际接口设计中,很多场景希望NULL字段直接不出现,避免前端拿到一堆没意义的空值。SQL Server 2022之前的版本要解决这个问题必须靠子查询和PATH的配合;SQL Server 2022之后有INCLUDE_NULL_VALUES和默认的行为变更。
2022及以上版本中,FOR JSON默认不再输出NULL值字段,这点和2019相反。如果你的项目还在2019上,但希望不输出NULL字段,一个可行方案是用JSON_MODIFY后处理,但那样太笨重。更实用的办法是在SELECT里就把NULL用CASE WHEN过滤掉,虽然繁琐但可控。
举一个2019环境下滤掉NULL字段的土办法:
sql复制SELECT
order_id,
NULLIF(customer_name, '') AS customer_name,
(CASE WHEN remark IS NOT NULL THEN remark END) AS remark
FROM orders
WHERE order_id = 1
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER;
当remark为NULL时,CASE返回NULL,2019的FOR JSON会把NULL字段输出为"remark":null,所以上面的写法其实并不能真正删除字段。真正的做法是利用子查询:
sql复制SELECT
order_id,
customer_name,
(SELECT remark WHERE remark IS NOT NULL) AS remark
FROM orders
WHERE order_id = 1
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER;
当remark为NULL时,子查询返回空结果,生成JSON时这个字段就会消失。这个技巧我早期研究了不少时间才弄明白,写在这里给同样被NULL困扰的人。
3.3 把JSON存到变量或导出
FOR JSON的结果可以直接赋值给变量,然后通过SELECT返回或者进一步处理:
sql复制DECLARE @json NVARCHAR(MAX);
SET @json = (
SELECT
order_id,
customer_name
FROM orders
WHERE order_id = 10086
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
);
SELECT @json AS order_json;
也可以直接用在INSERT里把JSON塞进另一张表,或者存到文件导出。SQL Server里没有直接的“导出JSON文件”命令,一般都是通过应用层取到结果后写文件,或者用bcp工具。
4. 修改、校验与性能优化:JSON_MODIFY的正确用法
4.1 JSON_MODIFY:在SQL里改JSON,不用先取出来再拼字符串
很多时候我们需要在数据库层面直接修改某个JSON字段里的某个值,比如更新订单JSON里的状态位、追加一条日志。SQL Server提供了JSON_MODIFY函数,语法如下:
sql复制JSON_MODIFY(expression, path, newValue)
它会在原JSON文本基础上做修改,返回修改后的新JSON字符串。newValue如果是普通字符串,会自动转义成JSON字符串;如果你要插入的是对象或数组,需要用JSON_QUERY包装一下,否则会被当成普通字符串处理。这一点非常关键,我们直接看例子。
假设原始JSON:
json复制{
"status": "pending",
"customer": {"name": "张三"},
"tags": ["普通"]
}
更新status字段:
sql复制DECLARE @json NVARCHAR(MAX) = N'{
"status": "pending",
"customer": {"name": "张三"},
"tags": ["普通"]
}';
SET @json = JSON_MODIFY(@json, '$.status', 'shipped');
-- 结果: {"status":"shipped","customer":{"name":"张三"},"tags":["普通"]}
替换整个customer对象:
sql复制SET @json = JSON_MODIFY(
@json,
'$.customer',
JSON_QUERY(N'{"name":"李四","phone":"139"}')
);
-- 结果: {"status":"shipped","customer":{"name":"李四","phone":"139"},"tags":["普通"]}
往tags数组里追加元素,需要利用lax模式下的自动创建特性:
sql复制SET @json = JSON_MODIFY(
@json,
'append $.tags',
'加急'
);
-- 结果: {"status":"shipped","customer":{"name":"李四","phone":"139"},"tags":["普通","加急"]}
关键心得:
- JSON_MODIFY的path支持用
append关键字向数组末尾追加元素 - 如果path指向的节点不存在,lax模式下会尝试创建(部分情况下)
- 修改的newValue如果是数字、布尔值、NULL,它会正确转换JSON类型,不会加引号
- 用JSON_MODIFY修改多个字段时,要多次调用,每调用一次生成一个新字符串,过程会有点繁琐
4.2 ISJSON做数据校验
ISJSON函数用来判断一个字符串是不是合法的JSON,返回1或0。最简单的场景是在表上建CHECK约束,防止非法JSON写入:
sql复制CREATE TABLE orders (
order_id INT PRIMARY KEY,
json_data NVARCHAR(MAX) NOT NULL,
CONSTRAINT ck_valid_json CHECK (ISJSON(json_data) = 1)
);
这样一来,插入或更新时如果json_data不是合法JSON,整条语句就会失败。这个约束对数据质量的保护非常有效,尤其在应用层经常拼JSON、容易拼错引号或漏括号的情况下。
另一个应用场景是在导入数据时做过滤:
sql复制SELECT *
FROM staging_import
WHERE ISJSON(raw_json) = 1;
先把不合法的行踢出去,再处理合法数据,避免在复杂的解析过程里因为个别坏数据崩掉。
4.3 JSON字段性能优化:计算列与索引
很多人在SQL Server里存了JSON后,最关心的就是查询性能。JSON字段本身是NVARCHAR(MAX),不能直接建索引,但我们可以通过计算列把JSON里的某个值提取出来,再在计算列上建索引。
流程分三步:
第一步,添加持久化计算列:
sql复制ALTER TABLE orders
ADD customer_name AS JSON_VALUE(json_data, '$.customer.name') PERSISTED;
第二步,建索引:
sql复制CREATE INDEX ix_orders_customer_name ON orders(customer_name);
第三步,查询时直接按计算列过滤:
sql复制SELECT *
FROM orders
WHERE customer_name = '张三';
这里有几个注意事项:
一是计算列引用JSON_VALUE函数时,函数必须标记为确定性函数才能持久化。JSON_VALUE对同一输入总是返回同一输出,所以满足确定性要求,实测可以PERSISTED。
二是计算列的类型是NVARCHAR(4000),因为JSON_VALUE返回类型就是NVARCHAR(4000)。如果你知道某个字段很可能是数字并要参与范围查询,建议CAST成对应的数值类型:
sql复制ALTER TABLE orders
ADD order_amount AS CAST(JSON_VALUE(json_data, '$.amount') AS DECIMAL(10,2)) PERSISTED;
这时候如果再建索引,等值查询和范围查询都能走索引。
三是不要对每个JSON字段都建计算列和索引,JSON的价值就在于灵活,如果你需要固定的字段做频繁过滤,说明这个字段应该被提炼成正式的关系列。我的建议是只对最核心、查询频率最高的两三个字段建计算列,其他仍然靠JSON原生解析。
4.4 处理大量JSON数据时的CPU与内存开销
JSON解析不是一个免费操作。每次调用JSON_VALUE、JSON_QUERY、OPENJSON,SQL Server都要实时解析字符串,大JSON文本或者复杂路径会让CPU占用明显升高。我处理过一个库存系统,一张表的json_data列平均长度达到几十KB,每次查询都调JSON_VALUE提取SKU,结果查询一多,CPU直接飙到90%以上。
优化思路非常明确:
第一,能用计算列提前提取的字段,尽量用计算列,把解析成本转移到写入时,查询时就变成普通的索引查找。
第二,尽量缩小JSON文本的搜索范围。在WHERE条件里先用其他关系列过滤掉大部分行,再对剩余行用JSON函数解析。不要一上来就全表扫JSON。
第三,避免在JSON_VALUE外面套函数。比如UPPER(JSON_VALUE(...))会导致无法使用索引,即使计算列本身有索引也没用。尽量在计算列上建好转换后的值。
第四,如果一个JSON字段频繁被整体读取且不需要在数据库里拆分,干脆就按NVARCHAR(MAX)直接返回给应用层,不要在SQL里做无意义的解析再拼回去,白白浪费CPU。
5. 常见问题与排查技巧实录
5.1 JSON_VALUE为什么返回NULL
这是问得最多的问题。路径没写错,但JSON_VALUE就是返回NULL。常见原因有四种:
第一,路径指向的不是标量值。查一下目标位置是对象还是数组,如果是对象/数组,请改用JSON_QUERY。
第二,JSON文本本身格式有问题,比如属性名漏了引号、逗号放错位置。先用ISJSON检查一下。
第三,属性名里带点号或特殊字符。比如{"a.b": 1},直接写$.a.b会被解析成两级路径,取不到值。正确写法是用双引号括起来:$."a.b"。
第四,JSON_VALUE是严格区分Unicode和非Unicode的,但一般不会因此返回NULL,更多是隐式转换的问题。如果值是'null'(字符串),JSON_VALUE返回的是字符串"null",而不是NULL,要注意区分。
5.2 路径里数组下标越界
lax模式下,$.items[99]如果数组只有2个元素,不会报错,返回NULL。这个行为对开发是友好的,但排查时容易误以为数据不对。建议先确认数组长度,用JSON_QUERY取出整个数组看一下,或者用OPENJSON统计行数。
5.3 OPENJSON和JSON_VALUE在NULL上的行为差异
OPENJSON把JSON里"field": null解析成SQL NULL,这是OK的。但JSON_VALUE对JSON里字段不存在和字段值为null都返回NULL,你无法区分。如果需要区分,就得用OPENJSON:
sql复制SELECT *, JSON_VALUE(value, '$.field') AS field_value
FROM OPENJSON(@json, '$.items')
因为OPENJSON的每行value是原样JSON,所以能保留“字段是否存在”的信息。不过大多数业务不需要区分这两种情况。
5.4 FOR JSON生成结果里为什么有反斜杠转义
当JSON文本里嵌套了另一个JSON字符串时,外层FOR JSON会对内层JSON做转义,把双引号变成\"。这是正常行为,因为内层JSON本质上是一个字符串,而不是结构化对象。如果希望内层JSON以对象形式嵌套输出,就需要用JSON_QUERY包装:
sql复制SELECT
order_id,
JSON_QUERY(json_data) AS json_data
FROM orders
FOR JSON PATH;
JSON_QUERY会告诉SQL Server这个值本身就是JSON,不要转义。
5.5 字符集和排序规则问题
JSON函数对Unicode和非Unicode的处理有细微区别。N'...'开头的Unicode字符串和普通字符串混用时,如果JSON文本里包含中文,建议统一用NVARCHAR(MAX)存储,避免中文字符被截断或乱码。否则遇到生僻字、表情符号时可能出问题。
5.6 版本兼容性速查
SQL Server 2016是最低门槛,支持JSON_VALUE、JSON_QUERY、JSON_MODIFY、OPENJSON、FOR JSON、ISJSON。SQL Server 2017和2019在这方面没有太大变化,主要是性能优化。SQL Server 2022新增了JSON_OBJECT和JSON_ARRAY两个构造函数,可以把标量值或子查询直接构造成JSON对象和数组:
sql复制SELECT
JSON_OBJECT('sku': sku, 'qty': qty) AS sku_info
FROM order_items
WHERE order_id = 1;
SQL Server 2025开始引入原生JSON类型,但2025还不是大多数生产环境的主力版本,这里就不展开了。
5.7 遇到json数据特别大、存储和传输都吃力,怎么办
一个实用经验是:别把JSON存得太大。JSON字段长到几十KB甚至几MB时,性能会断崖式下降,不管是查询解析还是应用层传输都很难受。如果遇到不得不存超大JSON的场景,要么压缩后在应用层解压,要么把JSON拆成多个表关联存储,只把最核心的扩展字段留在JSON里。我见过一个项目把整个商品详情页的渲染数据都塞进JSON,几十KB起步,最后查询性能惨不忍睹,被迫拆表。JSON不是万能筐,该拆的时候别犹豫。
另一个经验是:JSON字段尽量放在单独的表中,用主表和扩展表一对一关联。如果JSON是主表的一部分,查询主表时即使你只需要两个关系字段,也会连带把JSON读出来,白白增加IO开销。
结束语:写完这章,我的JSON查询经验基本都在这了
SQL Server的JSON功能总结起来就是八个字:字符串存,函数算。它不像MongoDB那样把JSON当成原生类型,但正因为这样,它才能完美融入SQL Server的关系型生态。在实际项目中,把JSON用在配置存储、弹性扩展字段、接口日志、结果集缓存这几个场景,收益是最明显的。
最后分享一个我个人的小习惯:凡是设计数据库表用到JSON列,我一定会在设计文档里标注“哪些字段会被提取成计算列、哪些函数会经常被调用、预期JSON最大长度”。这样后续接手的同事能快速了解这个JSON列是干什么用的,避免滥用导致性能劣化。JSON是一把好工具,但好工具也得配好使用者。
