CodeGym /Các khóa học /SQL SELF /So sánh JSON với các kiểu khác: ARRAY,

So sánh JSON với các kiểu khác: ARRAY, TEXT, HSTORE

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

So sánh JSON với các kiểu khác: ARRAY, TEXT, HSTORE

Trong PostgreSQL, nhiều dev thường gặp câu hỏi: nên dùng cấu trúc dữ liệu nào để lưu thông tin? Dùng mảng (ARRAY) cho cấu trúc dữ liệu đơn giản? Hay trường text (TEXT) cho chuỗi? Hoặc HSTORE để lưu các cặp "khóa-giá trị"? Và tất nhiên, câu hỏi lớn: khi nào thì nên dùng JSON hoặc JSONB?

Để giúp bạn rõ hơn, tụi mình sẽ nói về ưu nhược điểm của từng cách, kèm ví dụ sử dụng thực tế.

Khi nào dùng mảng (ARRAY), khi nào dùng JSONB?

Mảng (ARRAY) cực hợp cho dữ liệu đồng nhất, kiểu như một danh sách các giá trị cùng loại. Ví dụ, nếu bạn có danh sách điểm số của sinh viên hoặc các tag cho một bản ghi, mảng là best choice.

Ví dụ về mảng:

CREATE TABLE students (
    id SERIAL PRIMARY KEY,
    name TEXT,
    grades INTEGER[] -- mảng điểm số
);

INSERT INTO students (name, grades)
VALUES ('Alice', ARRAY[90, 85, 88]),
       ('Bob', ARRAY[70, 75, 78]);

Mặt khác, JSONB hợp với cấu trúc phức tạp, lồng nhau. Nếu bạn muốn lưu thêm info cho từng điểm, ví dụ mô tả từng điểm số, thì JSONB là chuẩn bài.

Ví dụ về JSONB:

CREATE TABLE students_json (
    id SERIAL PRIMARY KEY,
    name TEXT,
    grades JSONB -- object chứa info điểm số
);

INSERT INTO students_json (name, grades)
VALUES ('Alice', '{"Toán": 90, "Khoa học": 85, "Tiếng Anh": 88}'),
       ('Bob', '{"Toán": 70, "Khoa học": 75, "Tiếng Anh": 78}');

Khác biệt chính

Tiêu chí Mảng (ARRAY) JSONB
Cấu trúc Dữ liệu đồng nhất cùng kiểu Cấu trúc dữ liệu phức tạp, lồng nhau
Truy cập dữ liệu Theo index: grades[1] Theo key: grades->'Toán'
Hỗ trợ index Chỉ GIN hoặc BTREE cho cả mảng Index GINBTREE tiện cho từng key
Khi nào dùng Danh sách đơn giản (tag, điểm số, id) Object phức tạp với key và value

Ví dụ chuyển đổi giữa mảng và JSONB

Cùng xem cách chuyển dữ liệu giữa mảng và JSONB nhé:

Mảng → JSONB

SELECT to_jsonb(grades) AS grades_jsonb
FROM students;

-- Kết quả:
-- [{"90","85","88"}]

JSONB → Mảng

SELECT array_agg(value::INTEGER) AS grades_array
FROM jsonb_array_elements_text('["90", "85", "88"]');
-- Kết quả:
-- {90,85,88}

So sánh JSONB và dữ liệu text (TEXT)

Trường text cực hợp nếu bạn chỉ cần lưu chuỗi hoặc dữ liệu không có cấu trúc. Nếu bạn chỉ cần tìm kiếm theo chuỗi, ví dụ tên sản phẩm hoặc mô tả, TEXT là lựa chọn hợp lý.

CREATE TABLE books (
    id SERIAL PRIMARY KEY,
    title TEXT,
    description TEXT
);

INSERT INTO books (title, description)
VALUES ('Cơ bản SQL', 'Giới thiệu ngắn gọn về SQL'),
       ('PostgreSQL nâng cao', 'Hướng dẫn chi tiết về hiệu năng PostgreSQL');

Khi nào nên dùng JSONB?

Nếu chuỗi của bạn bắt đầu thành info có cấu trúc lồng nhau (ví dụ mô tả có category và danh sách tag), nên chọn JSONB.

CREATE TABLE books_json (
    id SERIAL PRIMARY KEY,
    info JSONB
);

INSERT INTO books_json (info)
VALUES ('{"title": "Cơ bản SQL", "tags": ["người mới", "cơ sở dữ liệu"]}'),
       ('{"title": "PostgreSQL nâng cao", "tags": ["hiệu năng", "tối ưu"]}');

Khác biệt chính

Tiêu chí Text (TEXT) JSONB
Cấu trúc Dữ liệu không có cấu trúc Dữ liệu có cấu trúc, lồng nhau
Tìm kiếm Tìm kiếm toàn văn bản Tìm theo key, value, cấu trúc lồng nhau
Thay đổi dữ liệu Chỉ thay thế toàn bộ Thay đổi từng key riêng lẻ
Khi nào dùng Chuỗi text đơn giản Dữ liệu phức tạp kiểu key-value

So sánh JSONB và HSTORE

HSTORE là kiểu dữ liệu "anh cả" của JSONB, cho phép lưu các cặp "khóa-giá trị". Nếu cấu trúc dữ liệu của bạn đơn giản (không cần lồng nhau hay mảng), HSTORE sẽ nhẹ và nhanh hơn.

CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    attributes HSTORE
);

INSERT INTO products (attributes)
VALUES ('"màu"=>"đỏ", "size"=>"M"'),
       ('"màu"=>"xanh", "size"=>"L"');

Tại sao JSONB thay thế HSTORE?

HSTORE tiện cho cặp "khóa-giá trị", nó không hỗ trợ lồng nhau hay mảng, nên JSONB đa năng hơn nhiều. Khi bạn cần object phức tạp hơn, JSONB là bước tiếp theo tự nhiên.

Khác biệt chính

Tiêu chí HSTORE JSONB
Cấu trúc Cặp "khóa-giá trị", không lồng nhau Cấu trúc lồng nhau đầy đủ
Hỗ trợ mảng Không
Tìm kiếm Chỉ theo key Theo key, value, cấu trúc lồng nhau
Khi nào dùng Key-value đơn giản Cấu trúc dữ liệu phức tạp

Làm sao chọn kiểu dữ liệu phù hợp?

Nếu bạn có:

  • Cấu trúc đơn giản — danh sách hoặc dữ liệu đồng nhất, dùng mảng (ARRAY).
  • Chuỗi đơn giản hoặc mô tả, dùng trường text (TEXT).
  • Cặp "khóa-giá trị" không lồng nhau, chọn HSTORE.
  • Object lồng nhau, mảng, cấu trúc phức tạp — bạn cần JSONB.

Ví dụ chuyển đổi giữa các định dạng

TEXT → JSONB

SELECT to_jsonb('Ví dụ text đơn giản') AS jsonb_form;
-- Kết quả: "Ví dụ text đơn giản"

JSONB → TEXT

SELECT info::TEXT AS text_form
FROM books_json;
-- Kết quả: {"title": "Cơ bản SQL", "tags": ["người mới", "cơ sở dữ liệu"]}

HSTORE → JSONB

SELECT hstore_to_jsonb(attributes) AS jsonb_form
FROM products;
-- Kết quả: {"màu": "đỏ", "size": "M"}

JSONB → HSTORE

SELECT jsonb_to_hstore('{"màu": "đỏ", "size": "M"}') AS hstore_form;
-- Kết quả: "màu"=>"đỏ", "size"=>"M"

Lưu ý gì khi chọn?

Nếu bạn cần linh hoạt tối đa và hỗ trợ cấu trúc phức tạp, chọn JSONB. Nhưng nếu bài toán chỉ cần cấu trúc đơn giản như mảng, text hoặc cặp "khóa-giá trị", hãy dùng kiểu dữ liệu tương ứng (ARRAY, TEXT, HSTORE).

Đừng quên, chọn đúng cấu trúc dữ liệu sẽ giúp bạn tránh đau đầu về sau và tăng hiệu năng cho query của bạn.

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION