CodeGym /课程 /SQL SELF /处理JSON数据时常见的错误以及如何避免

处理JSON数据时常见的错误以及如何避免

SQL SELF
第 34 级, 课程 4
可用

在PostgreSQL里用JSON数据其实挺强大的,但就像所有工具一样,用的时候得小心。哪怕是很小的失误,也能让你的查询变成一团乱麻。 今天我们又来聊聊在PostgreSQL里用JSON和JSONB时最常见的错误,还有怎么避免这些坑。

问题1:用JSON而不是JSONB

很多刚入门的小伙伴会误以为JSON类型是存JSON数据的最佳选择。其实JSON在PostgreSQL里就是纯文本存储,这样一来查找或过滤的时候性能会很差。

错误示例:

CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    details JSON
);

INSERT INTO products (details) VALUES ('{"name": "Laptop", "price": 1000}');

INSERT INTO products (details) VALUES ('{"name": "Laptop", "price": 1000}');

如果你想按price这个key来过滤,速度会比用JSONB慢很多。

怎么改: 如果你打算经常过滤或者查数据,直接用JSONB吧。

CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    details JSONB
);

问题2:JSONB没加索引

JSONB真的很强大,但如果你不加索引,复杂查询的时候性能会掉得很厉害。

错误示例:假设你有个表,details这一列存了很多JSON对象:

SELECT * FROM products WHERE details->>'name' = 'Laptop';

如果没加索引,数据库就只能全表扫描(full table scan),那速度就很慢了。

怎么改: 给key加个GIN索引,查起来就快多了:

CREATE INDEX idx_details_name ON products USING gin (details jsonb_path_ops);

问题3:取嵌套数据时出错

从嵌套对象或数组里取数据很容易搞混,尤其是你还没搞清楚->和->>这俩操作符的区别时。

错误示例:

SELECT details->'price' FROM products;

这个查询返回的是JSON格式的值,不是字符串("1000"而不是1000)。如果你想要直接拿到值,要用->>:

SELECT details->>'price' FROM products;

问题4:操作符用错了

你可能见过@>这个操作符,觉得:“看起来挺酷的,直接用!”但如果你没搞懂它怎么用,结果可能会很奇怪。

错误示例:

SELECT * FROM products WHERE details @> '{"price": 1000}';

这个查询只有在JSON里的price是数字时才有效。如果price存成了字符串"1000",那啥都查不到。

怎么改: 注意JSON里的数据类型:

SELECT * FROM products WHERE details->>'price' = '1000';

问题5:JSON对象太大

如果你啥都往一个大JSON对象里塞,不做优化,查询会慢得要命。而且,哪怕你只改JSONB里的一小部分,PostgreSQL也得处理整个对象。

怎么改: 如果有些key经常用,直接单独建成表字段。比如:

ALTER TABLE products ADD COLUMN price NUMERIC;
UPDATE products SET price = (details->>'price')::NUMERIC;

这样你就能高效地过滤和排序了,不用每次都拆JSONB。

问题6:每次改都重建整个对象

用jsonb_set()或者jsonb_insert()这些函数时,PostgreSQL会生成一个全新的JSONB对象,这对性能来说挺费劲的。

怎么改: 尽量减少对JSONB的更新。比如,不要频繁地改同一个对象,可以把所有改动合成一次操作:

UPDATE products
SET details = jsonb_set(details, '{price}', '1500'::jsonb);

问题7:没搞懂数组结构

JSONB里的数组也得小心用。假设你有个数组:

{
    "tags": ["electronics", "laptop", "sale"]
}

你想查有没有"laptop"这个tag。如果你用错了@>操作符,可能啥都查不到,因为它要的是数组,不是字符串。

错误示例:

SELECT * FROM products WHERE details->'tags' @> '"laptop"';

怎么改: @>操作符里要用正确的格式:

SELECT * FROM products WHERE details->'tags' @> '["laptop"]';

避免错误的小建议

想在用JSONB时少踩坑,可以试试这些做法:

选对数据类型。 如果你数据量大、经常查,直接用JSONB,别用JSON。

加索引。 如果经常查某些key,记得加合适的索引(比如GIN)。

插入前先检查数据。 用校验函数检查数据结构:

DO $$
BEGIN
    IF jsonb_typeof('{"price": 1000}'::jsonb->'price') IS DISTINCT FROM 'number' THEN
        RAISE EXCEPTION '价格必须是数字';
    END IF;
END $$;

优化数据结构。 如果有些key用得特别多,直接单独建成表字段。

多了解操作符和函数。 多看看PostgreSQL官方文档,搞清楚->、->>、@>、?|等操作符和函数的区别。

JSON和JSONB能帮你灵活处理各种复杂数据。关键是选对工具,避开常见的坑,这样你的代码才又快又好维护。

2
任务
SQL SELF, 第 34 级, 课程 4
已锁定
根据JSONB中的值进行数据过滤
根据JSONB中的值进行数据过滤
1
调查/小测验
在JSON对象中更新数据第 34 级,课程 4
不可用
在JSON对象中更新数据
在JSON对象中更新数据
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION