CodeGym /Các khóa học /SQL SELF /Những lỗi thường gặp khi làm việc với dữ liệu JSON và các...

Những lỗi thường gặp khi làm việc với dữ liệu JSON và cách tránh chúng

SQL SELF
Mức độ, Bài học
Có sẵn

Làm việc với dữ liệu JSON trong PostgreSQL là một công cụ cực mạnh, nhưng cũng như mọi công cụ khác, phải dùng cẩn thận. Chỉ một lỗi nhỏ thôi là truy vấn của bạn thành một câu đố khó nhằn ngay. Hôm nay tụi mình lại tập trung vào những lỗi thường gặp khi làm việc với JSON và JSONB trong PostgreSQL, cùng với cách phòng tránh nhé.

Vấn đề 1: dùng JSON thay vì JSONB

Nhiều bạn mới học hay nhầm lẫn chọn kiểu dữ liệu JSON, nghĩ nó là lựa chọn tốt nhất để lưu dữ liệu dạng JSON. Nhưng JSON trong PostgreSQL lưu dữ liệu dưới dạng text, dẫn đến hiệu năng giảm khi tìm kiếm hay lọc dữ liệu.

Ví dụ lỗi:

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}');

Khi thử lọc theo key (price), tốc độ sẽ chậm hơn nhiều so với JSONB.

Cách sửa: hãy dùng JSONB nếu bạn định lọc hoặc truy cập dữ liệu thường xuyên.

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

Vấn đề 2: không tạo index cho JSONB

JSONB là một công cụ cực mạnh, nhưng nếu không có index thì hiệu năng khi truy vấn phức tạp sẽ giảm rõ rệt.

Ví dụ lỗi: giả sử bạn có một bảng với cột details, nơi lưu rất nhiều object JSON:

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

Nếu dữ liệu không được index, server sẽ phải quét toàn bộ bảng (full table scan), tốn rất nhiều thời gian.

Cách sửa: tạo index GIN để tăng tốc tìm kiếm theo key:

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

Vấn đề 3: lỗi khi truy xuất dữ liệu lồng nhau

Lấy dữ liệu từ object hoặc array lồng nhau dễ gây rối, nhất là khi bạn chưa rõ sự khác biệt giữa toán tử -> và ->>.

Ví dụ lỗi:

SELECT details->'price' FROM products;

Truy vấn này trả về giá trị dạng JSON, chứ không phải string ("1000" thay vì 1000). Nếu bạn cần giá trị thực, hãy dùng ->>:

SELECT details->>'price' FROM products;

Vấn đề 4: Dùng sai toán tử

Có thể bạn từng gặp toán tử @> và nghĩ: "Nghe hay phết, dùng luôn cho mọi trường hợp!" Nhưng nếu không hiểu rõ cách nó hoạt động, bạn sẽ nhận kết quả bất ngờ đấy.

Ví dụ lỗi:

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

Truy vấn này chỉ hoạt động nếu price là số trong JSON. Nếu giá trị lưu dưới dạng string "1000", truy vấn sẽ không trả về gì cả.

Cách sửa: hãy chú ý đến kiểu dữ liệu trong JSON:

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

Vấn đề 5: Object JSON quá lớn

Lưu object JSON lớn mà không tối ưu sẽ làm truy vấn chậm hẳn. Thậm chí, chỉ cần đọc hay sửa một phần nhỏ trong JSONB cũng phải xử lý toàn bộ object.

Cách sửa: nếu một số key được dùng thường xuyên, hãy tách chúng ra thành cột riêng trong bảng. Ví dụ:

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

Bây giờ bạn có thể lọc và sắp xếp dữ liệu hiệu quả mà không cần parse JSONB nữa.

Vấn đề 6: Phải xây lại toàn bộ object khi thay đổi

Khi dùng các hàm như jsonb_set() hoặc jsonb_insert(), PostgreSQL sẽ tạo ra một object JSONB hoàn toàn mới, khá tốn tài nguyên.

Cách sửa: giảm số lần cập nhật JSONB. Ví dụ, thay vì cập nhật từng tí một, hãy gộp các thay đổi vào một truy vấn:

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

Vấn đề 7: Không hiểu cấu trúc array

Array trong JSONB cũng cần chú ý. Giả sử bạn có một array như sau:

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

Bạn muốn kiểm tra xem có tag "laptop" không. Nếu dùng sai toán tử @>, bạn sẽ không nhận được kết quả, vì nó cần array chứ không phải string.

Ví dụ lỗi:

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

Cách sửa: Dùng đúng format cho toán tử @>:

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

Mẹo để tránh lỗi

Để tránh nhiều vấn đề khi làm việc với JSONB, hãy làm theo các mẹo sau:

Chọn đúng kiểu dữ liệu. Nếu bạn làm với dữ liệu lớn và hay lọc, luôn dùng JSONB thay vì JSON.

Tạo index cho dữ liệu. Nếu truy vấn thường xuyên theo một số key, hãy tạo index phù hợp (ví dụ GIN).

Kiểm tra dữ liệu trước khi insert. Dùng các hàm validate để kiểm tra cấu trúc dữ liệu:

DO $$
BEGIN
    IF jsonb_typeof('{"price": 1000}'::jsonb->'price') IS DISTINCT FROM 'number' THEN
        RAISE EXCEPTION 'Giá phải là số';
    END IF;
END $$;

Tối ưu cấu trúc dữ liệu. Nếu một số key được dùng nhiều, hãy tách chúng ra thành cột riêng trong bảng.

Tìm hiểu kỹ các toán tử và hàm. Đọc kỹ tài liệu chính thức của PostgreSQL để hiểu rõ sự khác biệt giữa ->, ->>, @>, ?| và các hàm khác.

JSON và JSONB có thể là bạn đồng hành tuyệt vời khi làm việc với dữ liệu linh hoạt và phức tạp. Quan trọng là chọn đúng công cụ và tránh các lỗi phổ biến để code của bạn vừa hiệu quả vừa dễ bảo trì nhé.

2
Nhiệm vụ
SQL SELF, mức độ, bài học
Đã khóa
Lọc dữ liệu theo giá trị trong JSONB
Lọc dữ liệu theo giá trị trong JSONB
1
Khảo sát/đố vui
, cấp độ , bài học
Không có sẵn
Cập nhật dữ liệu trong các đối tượng JSON
Cập nhật dữ liệu trong các đối tượng JSON
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION