CodeGym /Các khóa học /SQL SELF /So sánh mảng và JSONB

So sánh mảng và JSONB

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

Hôm nay tụi mình sẽ đào sâu hơn về mảng và so sánh kỹ hơn với JSONB, xem điểm mạnh/yếu của từng cái và chọn best practice để áp dụng vào bài toán thực tế.

Mảng vs JSONB: mini rùa dữ liệu vs hộp linh hoạt

Bạn chắc cũng biết rồi, trong mảng của PostgreSQL thì chỉ lưu được giá trị cùng một kiểu dữ liệu thôi: mảng số, chuỗi hoặc ngày tháng. Ví dụ: danh sách điểm của sinh viên, tất cả phần tử đều là số.

-- Bảng sinh viên và điểm của họ
CREATE TABLE students (
    id SERIAL PRIMARY KEY,
    name TEXT,
    grades INTEGER[]    -- mảng điểm
);

JSONB thì khác, nó lưu dữ liệu dạng cấu trúc JSON. Nhìn giống object trong JavaScript mà ai cũng quen, nhưng có lợi thế là parse nhanh và index tốt. Trong JSONB bạn có thể lưu cả list lẫn object với key-value luôn.

-- Bảng sinh viên và các thông tin khác nhau về họ
CREATE TABLE students_details (
    id SERIAL PRIMARY KEY,
    name TEXT,
    details JSONB  -- cấu trúc JSON linh hoạt
);

Ví dụ dữ liệu trong JSONB:

{
    "grades": [90, 82, 77],
    "address": {
        "city": "Berlin",
        "zip": "352912"
    }
}

Vậy là, mảng là cách đơn giản để làm việc với danh sách giá trị, còn JSONB thì cho bạn nhiều lựa chọn hơn cho dữ liệu phức tạp.

Khác biệt chính giữa mảng và JSONB

Tiêu chí Mảng JSONB
Kiểu cấu trúc Cấu trúc dữ liệu tuyến tính Cấu trúc dữ liệu phân cấp
Kiểu phần tử Chỉ một kiểu dữ liệu Nhiều kiểu dữ liệu khác nhau
Kích thước cấu trúc Cố định (tuyến tính) Linh hoạt, có thể gồm list và object
Tốc độ truy cập Nhanh khi dữ liệu cố định Chậm hơn khi tìm kiếm phức tạp
Indexing Hỗ trợ indexing tốt Cần index kiểu GIN
Ứng dụng Danh sách đơn giản hoặc mảng giá trị Dữ liệu phức tạp: object/list lồng nhau

Giờ thử xem thực tế nó chạy ra sao nhé.

Khi nào dùng mảng?

Giả sử bạn có database sách, mỗi cuốn có thể thuộc nhiều thể loại. Mảng là lựa chọn ngon lành ở đây.

CREATE TABLE books (
    id SERIAL PRIMARY KEY,
    title TEXT,
    genres TEXT[]    -- mảng thể loại
);

-- Ví dụ insert sách với nhiều thể loại
INSERT INTO books (title, genres)
VALUES ('1984', ARRAY['Dystopia', 'Political Fiction', 'Science Fiction']);

Mảng hợp lý nếu bạn chắc rằng:

  • dữ liệu của bạn lưu được thành list rõ ràng,
  • list nhỏ và cùng kiểu (ví dụ chuỗi hoặc số),
  • bạn chỉ cần lưu/truy xuất list (không cần thao tác phức tạp).

Ưu điểm của mảng

  • Lưu dữ liệu cùng kiểu rất đơn giản.
  • Tiện cho list nhỏ như tag, category hoặc điểm số.

Khi nào dùng JSONB?

Giờ giả sử bạn muốn lưu dữ liệu phức tạp hơn về sách, gồm thể loại, ISBN và rating. Mảng không còn hợp nữa — lúc này JSONB lên ngôi.

CREATE TABLE books_details (
    id SERIAL PRIMARY KEY,
    title TEXT,
    details JSONB    -- chi tiết sách dạng JSONB
);

-- Ví dụ insert thông tin phức tạp về sách
INSERT INTO books_details (title, details)
VALUES (
    '1984',
    '{"genres": ["Dystopia", "Political Fiction", "Science Fiction"],
      "isbn": "9780451524935",
      "rating": 8.9}'
);

JSONB ngon nếu bạn cần:

  • lưu dữ liệu phức tạp hoặc nhiều kiểu (số, chuỗi, list, object),
  • thêm thuộc tính động mà không phải sửa cấu trúc bảng,
  • lưu dữ liệu lồng nhau (ví dụ địa chỉ, đặc điểm, cài đặt).

Ưu điểm của JSONB

  • Linh hoạt cực cao. Thêm key/value mới mà không phải sửa bảng.
  • Hợp để lưu dữ liệu phức tạp, ví dụ response JSON từ API.

Chọn giữa mảng và JSONB

Nếu chỉ lưu list cùng kiểu — dùng mảng. Ví dụ:

-- Lưu ID người tham gia sự kiện
CREATE TABLE events (
    id SERIAL PRIMARY KEY,
    participant_ids INTEGER[]
);

Nếu dữ liệu phức tạp hoặc nhiều kiểu — nên dùng JSONB. Ví dụ:

-- Lưu thông tin khách hàng kèm địa chỉ
CREATE TABLE customers (
    id SERIAL PRIMARY KEY,
    info JSONB
);

Về indexing thì mảng và JSONB có cách khác nhau. Mảng thường dùng index GIN, còn JSONB thì GINBTREE, tuỳ cấu trúc dữ liệu.

Hiệu năng

Mảng xử lý nhanh hơn với các truy vấn tìm kiếm cơ bản. JSONB hơi chậm hơn, nhưng lại linh hoạt. Nếu bạn chỉ cần tìm phần tử (ví dụ thể loại hoặc ID), mảng sẽ nhanh hơn:

-- Dùng mảng với index GIN
CREATE INDEX idx_genres ON books USING GIN(genres);

-- Lọc sách theo thể loại
SELECT * FROM books WHERE genres @> ARRAY['Science Fiction'];

Kiểm tra dữ liệu tồn tại

JSONB có nhiều lựa chọn filter theo key hơn:

-- Kiểm tra key "genres" có tồn tại không
SELECT * FROM books_details WHERE details ? 'genres';

-- Kiểm tra phần tử trong list
SELECT * FROM books_details WHERE details->'genres' ?| ARRAY['Fantasy', 'Dystopia'];

Mảng thì tìm giá trị trực tiếp luôn:

-- Kiểm tra phần tử trong mảng
SELECT * FROM books WHERE genres @> ARRAY['Fantasy'];

Linh hoạt cấu trúc

JSONB là chân ái nếu dữ liệu có cấu trúc lồng nhau phức tạp:

{
    "genres": ["Fantasy", "Adventure"],
    "ratings": {"goodreads": 8.5, "amazon": 4.7}
}

Mảng thì không làm được chuyện này nếu không chuẩn hoá hoặc thêm trường phụ.

Kết lại, mảng và JSONB không phải đối thủ mà là công cụ cho từng bài toán khác nhau. Nếu dữ liệu kiểu list — dùng mảng. Nếu dữ liệu phức tạp, lồng nhau hoặc nhiều kiểu — cứ mạnh dạn chọn JSONB. Quan trọng là nhớ hiệu năng và indexing nhé!

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