Một trong những điểm khác biệt chính giữa JSON và JSONB là định dạng lưu trữ dữ liệu. JSON lưu dữ liệu dưới dạng text, còn JSONB thì lưu ở dạng nhị phân. Điều này có nghĩa là:
- JSON lưu dữ liệu đúng như bạn truyền vào. Ví dụ, nếu bạn insert chuỗi
{"title": "PostgreSQL", "tags": ["database", "SQL"]}, nó sẽ được lưu y nguyên như vậy. - JSONB sẽ parse object JSON trước, loại bỏ khoảng trắng thừa, sắp xếp lại các key, tối ưu cấu trúc rồi mới lưu ở dạng nhị phân.
Việc tối ưu này giúp JSONB xử lý dữ liệu nhanh hơn, đặc biệt khi thực hiện các truy vấn phức tạp như filter, search và sort.
Hiệu năng đọc và ghi
JSON và JSONB có các đặc điểm khác nhau về tốc độ đọc và ghi dữ liệu:
- JSON ghi vào database nhanh hơn vì không cần parse dữ liệu trước khi lưu. Tuy nhiên, việc đọc và xử lý dữ liệu thường chậm hơn, vì PostgreSQL phải parse lại dữ liệu khi thực hiện truy vấn.
- JSONB tốn nhiều thời gian ghi hơn, vì dữ liệu phải được xử lý trước khi lưu. Nhưng việc đọc, filter và lấy giá trị sẽ nhanh hơn nhiều, nên JSONB rất hợp cho các bài toán phân tích hoặc tìm kiếm.
Ví dụ cho dễ hình dung:
-- Tạo bảng với JSON và JSONB
CREATE TABLE json_example (data JSON);
CREATE TABLE jsonb_example (data JSONB);
-- Insert dữ liệu
INSERT INTO json_example VALUES ('{"key": "giá trị", "tags": ["json", "ví dụ"]}');
INSERT INTO jsonb_example VALUES ('{"key": "giá trị", "tags": ["jsonb", "ví dụ"]}');
-- Lọc dữ liệu
SELECT * FROM json_example WHERE data->'key' = '"giá trị"'; -- Chậm hơn
SELECT * FROM jsonb_example WHERE data->'key' = '"giá trị"'; -- Nhanh hơn
Indexing dữ liệu
Một trong những lợi thế lớn nhất của JSONB là hỗ trợ indexing. PostgreSQL cho phép tạo index cho cột JSONB bằng loại index GIN. Điều này giúp tăng tốc độ tìm kiếm và filter dữ liệu rất nhiều.
Ví dụ tạo index:
-- Index trên cột JSONB
CREATE INDEX idx_jsonb_tags ON jsonb_example USING gin (data->'tags');
JSON thì ngược lại, không hỗ trợ indexing, nên không phù hợp cho các thao tác tìm kiếm và filter phức tạp.
Khi nào dùng JSON, khi nào dùng JSONB
JSON hợp nhất khi:
- Bạn cần lưu dữ liệu đúng nguyên bản, không thay đổi gì.
- Bạn không định query filter, search hay sort nhiều trên dữ liệu JSON.
- Dữ liệu JSON chủ yếu dùng để truyền cho hệ thống khác hoặc client mà không chỉnh sửa (ví dụ trả về frontend qua API).
Ví dụ:
-- Lưu JSON mà không phân tích
CREATE TABLE api_responses (
id SERIAL PRIMARY KEY,
response JSON
);
-- Insert dữ liệu như nhận từ API
INSERT INTO api_responses (response)
VALUES ('{"status": "thành công", "payload": {"id": 123, "name": "John"}}');
Nên dùng JSONB nếu:
- Bạn định filter, search, group hoặc sort dữ liệu theo giá trị bên trong JSON.
- Hiệu năng truy cập dữ liệu quan trọng hơn tốc độ ghi.
- Bạn muốn dùng indexing để tăng tốc thao tác với dữ liệu JSON.
Ví dụ:
-- Lưu JSONB để phân tích và làm việc với object lồng nhau
CREATE TABLE products (
id SERIAL PRIMARY KEY,
details JSONB
);
-- Insert dữ liệu
INSERT INTO products (details)
VALUES ('{"name": "Laptop", "price": 1200, "tags": ["điện tử", "máy tính"]}');
-- Tìm sản phẩm có tag "điện tử"
SELECT * FROM products
WHERE details @> '{"tags": ["điện tử"]}';
Chi tiết về operator @> và --> sẽ có ở các bài giảng sau nhé :P
Ví dụ làm việc với JSON và JSONB
Tạo hai bảng: một bảng có cột JSON, một bảng có cột JSONB:
CREATE TABLE json_table (
id SERIAL PRIMARY KEY,
data JSON
);
CREATE TABLE jsonb_table (
id SERIAL PRIMARY KEY,
data JSONB
);
Insert dữ liệu giống nhau cho cả hai bảng:
INSERT INTO json_table (data)
VALUES ('{"key": "giá trị", "tags": ["json", "ví dụ"]}');
INSERT INTO jsonb_table (data)
VALUES ('{"key": "giá trị", "tags": ["jsonb", "ví dụ"]}');
Giờ thử lấy dữ liệu mà key key có giá trị giá trị:
-- Với JSON
SELECT * FROM json_table
WHERE data->>'key' = 'giá trị';
-- Với JSONB
SELECT * FROM jsonb_table
WHERE data->>'key' = 'giá trị';
Với dữ liệu nhỏ thì hiệu năng gần như không khác biệt. Nhưng nếu làm việc với hàng triệu dòng thì JSONB sẽ vượt trội, nhất là khi bạn tạo index:
CREATE INDEX idx_jsonb_key ON jsonb_table USING gin ((data->>'key'));
Làm việc với object lồng nhau và array cũng hiệu quả hơn với JSONB:
-- Lấy giá trị đầu tiên từ array
SELECT data->'tags'->>0 AS first_tag
FROM jsonb_table;
Ưu điểm và nhược điểm
| Đặc điểm | JSON | JSONB |
|---|---|---|
| Lưu trữ dữ liệu | Lưu dữ liệu ở dạng text gốc | Lưu dữ liệu ở dạng nhị phân, sắp xếp lại key |
| Hiệu năng ghi | Nhanh hơn vì lưu "nguyên bản" | Chậm hơn do phải parse trước |
| Hiệu năng đọc | Chậm hơn vì phải parse khi query | Nhanh hơn vì dữ liệu đã tối ưu cho đọc |
| Indexing | Không hỗ trợ | Có hỗ trợ (index GIN, BTREE) |
| Filter | Chậm | Nhanh |
| Hỗ trợ thao tác | Giới hạn | Mở rộng |
Việc chọn giữa JSON và JSONB phụ thuộc vào bài toán. Nếu chỉ cần lưu dữ liệu dạng text không đổi, cứ chọn JSON cho đơn giản. Nếu bạn định thao tác nhiều với dữ liệu trong cột, filter, search hay group, thì JSONB sẽ hiệu quả và tiện hơn nhiều.
Với các ứng dụng phức tạp, nơi dữ liệu JSON không chỉ là "kho lưu trữ" mà còn dùng nhiều cho phân tích, thì JSONB là công cụ không thể thiếu. Nên nếu phân vân — cứ chọn JSONB đi. Biết đâu sau này bạn sẽ có "truy vấn nhanh nhất đời" nhờ nó đấy!
GO TO FULL VERSION