5月27日 18:24
MariaDB 的 JSON 函数怎么用?有哪些常见坑?
MariaDB 从 10.2 开始提供了一套 JSON 函数,能直接在 SQL 里创建、查询、修改和校验 JSON 数据。JSON 列本质是 LONGTEXT 加 CHECK 约束,不是 MySQL 那种二进制格式,这一点在迁移时容易踩坑。
追问
JSON_EXTRACT、JSON_VALUE、JSON_QUERY 有什么区别?
三个都是取值,但返回类型不同:
| 函数 | 返回值 | 示例 |
|---|---|---|
| JSON_EXTRACT | 原始 JSON 片段(带引号) | "John" |
| JSON_VALUE | 标量值(去引号) | John |
| JSON_QUERY | 对象或数组 | {"city":"NY"} |
日常取字符串值用 -> 操作符(JSON_EXTRACT 的语法糖),取标量用 JSON_VALUE,取嵌套对象用 JSON_QUERY。
JSON_SET、JSON_INSERT、JSON_REPLACE 有什么区别?
- JSON_SET:存在则更新,不存在则插入——万能选手
- JSON_INSERT:只在路径不存在时插入,已有值不动
- JSON_REPLACE:只在路径已存在时替换,没找到就跳过
记住一句话:不确定用 SET,只想加新字段用 INSERT,只想改旧字段用 REPLACE。
JSON 列怎么加索引?
JSON 列不能直接建普通索引。两种方式:
- 生成列 + 索引(推荐):
sqlALTER TABLE products ADD COLUMN brand VARCHAR(50) GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(attributes, '$.brand'))) STORED, ADD INDEX idx_brand(brand);
- 函数索引(MariaDB 10.3+):
sqlCREATE INDEX idx_brand ON products((CAST(attributes->'$.brand' AS CHAR(50))));
MariaDB 的 JSON 和 MySQL 的 JSON 有什么区别?
这是迁移时最容易翻车的地方:
| 对比项 | MariaDB | MySQL |
|---|---|---|
| 存储格式 | 原文 LONGTEXT | 二进制 JSON |
| JSON 类型 | LONGTEXT 的别名 | 独立数据类型 |
| 自动校验 | 需要 CHECK 约束 | 内置校验 |
| 部分更新 | 不支持 | 支持二进制增量更新 |
MariaDB 存原文的好处是可以直接用文本函数处理,坏处是每次修改整个字段重写,大 JSON 字段更新性能差。
用 JSON 列存数据有什么坑?
- 没有 schema 约束:同列不同行结构可以完全不同,查出来才知道长什么样,排查问题靠蒙
- 查询性能:每次取值都要解析 JSON,高频查询字段务必抽成普通列加索引
- 更新代价:改一个字段整个 JSON 重写,大文档更新慢
- CHECK 约束别忘了加:
sqlCREATE TABLE products ( id INT PRIMARY KEY, attrs JSON, CONSTRAINT chk_json CHECK (JSON_VALID(attrs)) );
写段代码
sql-- 建表 + 插入 + 查询一条龙 CREATE TABLE products ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100), attrs JSON CHECK (JSON_VALID(attrs)) ); INSERT INTO products (name, attrs) VALUES ('Laptop', '{"brand":"Dell","ram":"16GB"}'); -- 查品牌、改内存 SELECT name, attrs->'$.brand' AS brand FROM products; UPDATE products SET attrs = JSON_SET(attrs, '$.ram', '32GB') WHERE id = 1;