0

Sử dụng kiểu dữ liệu phi cấu trúc trong Postgres hỗ trợ NoSQL

Từ khi Postgres hỗ trợ NoSQL (với hstore, json và jsonb), câu hỏi sử dụng Postgres theo mô hình quan hệ hay mô hình NoSQL thường xuyên được đăt ra. Bạn sẽ bỏ hoàn toàn kiểu dữ liệu cấu trúc bảng và chuyển hẳn sang dùng documents? Hay là kết hợp cả hai? Câu trả lời không có gì lấy làm ngạc nhiên: còn tùy! Mỗi mô hình mới bao gồm Hstore, JSON và JSONB có hoàn cảnh sử dụng hợp lý của chúng. Bây giờ chúng ta sẽ đào sâu hơn vào mỗi loại và xem xem khi nào thì bạn quyết định sử dụng cái nào.

HStore

Nếu không tính đến XML (Postgre có hỗ trợ kiểu dữ liệu XML),đây là kiểu “dữ liệu phi cấu trúc” đầu tiên xuất hiện trên Postgres. Hstore có mặt ở phiên bản Postgres 8.3, trước cả các tính năng upsert, streaming replication hay window functions.  Hstore là dạng lưu trữ  key/value trong Postgres. Với hstore, bạn gặp một chút hạn chế về kiểu dữ liệu: chỉ dùng string. Bạn cũng không thể lưu trữ đa cấp hay dữ liệu phức tạp; nói đơn giản thì hstore là một kiểu dữ liệu thực sự thuần key/value.

Ưu điểm của hstore là bạn không cần định nghĩa trước bất kỳ keys nào. Bạn có thể đơn giản insert record và nó có thể chứa bất cứ thứ gì. Ví dụ ta có một bảng ví dụ:

Từ bây giờ, bạn có thể insert bất cứ thứ gì vào cột attributes. Và sau đó truy vấn dựa trên những cặp keys/values đó:

Hiển nhiên, lợi ích ở đây là tính linh hoạt, nhưng htstore chỉ thực sự tỏa sáng trên sân khấu Index. Cụ thể, một index GIN hay GiST sẽ index mọi key và value trong hstore. Bằng cách này, khi truy vấn gì đó, Postgres sẽ sử dụng index và tìm kiếm cực kỳ hiệu quả.

Hstore không thể lưu trữ full document – chỉ string – cho nên phải cân nhắc kỹ càng khi muốn dùng. Nếu bạn có dữ liệu quan hệ bên cạnh một số dữ liệu có thể không thuộc một cột xác định: Hstore có thể thích hợp. Trong hầu hết các trường hợp tương tự các thuộc tính của một sản phẩm trong trong catalog nhiều loại mặt hàng khác nhau, có thể là một ví dụ chính xác nhất về hstore. Mặt hàng có thể là sách với thuộc tính tác giả, mã isbn; cũng có thể là giày dép với thuộc tính size, màu sắc.

JSON

Postgres 9.2 đến cùng với JSON. Cuối cùng thì Postgres đã có thể hoàn toàn đối chọi với MongoDB (mặc dù chức năng xử lý JSON trong Postgres 9.2 thì vẫn còn tương đối ít ỏi).

Kiểu dữ liệu JSON trong Postgres nằm dưới vỏ bọc là một text field. Nhưng với khả năng thực thi validation, Potsgres đã thực sự xem JSON là JSON chứ không phải text field. Một điểm hơn so với JSONB (kiểu dữ liệu chúng ta sẽ tìm hiểu ngay bên dưới) đó là nó giữ nguyên preformated text, các dấu xuống dòng, khoảng trắng hay các dấu thụt đầu dòng. Vậy câu hỏi đặt ra: bạn có nên dùng JSON? Nếu bạn thực sự cần giữ format của JSON theo kiểu dành-cho-loài-người (human readable), ít khi truy vấn, các dữ liệu dạng log thì JSON có thể sẽ hữu dụng. Còn lại, tôi đề nghị bạn nên dùng JSONB như dưới đây.

JSONB

Cuối cùng ở bản Postgres 9.4, chúng ta cũng có được định dạng JSON thực sự đúng đắn dưới cái tên JSONB. Chữ B là viết tắt của better. JSON được lưu trữ dưới dạng kiểu như file nhị phân (chứ không phải text field như JSON), điều này đồng nghĩa với việc dữ liệu được nén và hiệu quả hơn trong việc lưu trữ. Điểm này phần nào giống với Hstore. Thực ra, đã có một thời gian có hai kiểu riêng biệt là HStore2 và JSON, nay chúng được hợp nhất lại thành JSONB.

JSONB phổ quát hầu hết những gì bạn mong muốn ở một kiểu dữ liệu JSON – documents NoSQL. Nó chấp nhận nested-structures, không biết dịch sao luôn, đại khái là Object lồng trong Object – đa cấp. Kết hợp với tạo GIN index trên JSONB column sẽ tạo index trên mọi key/value trong JSON document. Khả năng tạo INDEX chính là phần nào học hỏi từ hstore nhưng lại vượt trội hơn so với Hstore nhờ nested-structure. Đúng JSONB chính là từ Hstore + JSON mà thành!

Vẫn còn lại vài câu hỏi nhỏ về khi nào sử dụng JSONB. Nếu bạn muốn một cơ sở dữ liệu document NoSQL, thay vì vì lăn tăn lựa chọn MySQL hay MongoDB, bây giờ bạn có thể dùng ngay Postgres. Một vài ví dụ phổ biến:

  • Dữ liệu theo dõi sự kiện, khi mà mỗi sự kiện có thể đính kèm payload với các  thông số khác nhau.
  • Dữ liệu game thì đặc biệt thích hợp, ví dụ mỗi người chơi tuy chơi cùng nhân vật nhưng sẽ có các hệ thống thông số khác nhau khi khác đẳng cấp, khác cách build đồ, lên kỹ năng…
  • Công cụ tương tác với nhiều nguồn data, ví dụ như các công cụ chuyên fetch data khách hàng từ các website khác thì mỗi website nguồn sẽ có định dạng, nội dung khác nhau.

Thử ngó nhanh qua một ví dụ nữa đễ xem JSONB hoạt động thế nào. Đầu tiên tạo bảng và insert vài dòng:

Trong ví dụ trên, tôi có thể dễ dàng tìm ra tất cả các record có email là [email protected] rồi thực hiện vài hành động. Điều này tương tự như hành vi phân tích kiểu như tìm ra các user đã làm việc X thì đưa ra báo cáo về nội dung Y. Bằng cách thêm GIN index: CREATE INDEX idx_integrations_data ON integrations USING gin(data); Tất cả dữ liệu trong JSONB sẽ tự động được index.

Kết luận

Trong hầu hết trường hợp, JSONB sẽ đáp ứng tốt nhu cầu mà bạn đang tìm kiếm ở NoSQL như schema-less, datatype, nested-structer. Hstore và JSON vẫn có vị trí của chúng, tuy ít thông dụng. Xét rộng hơn, JSONB không phải là luôn tương thích với mọi data model. Nhưng chỗ nào bạn cần một schema với lượng lớn các thuộc tính động, hay là nhiều schema khác nhau dựa trên các khách hàng khác nhau thì JSONB là một sự lựa chọn tuyệt vời! Nhìn chung, bạn sẽ muốn dùng:

  • JSONB – trong hầu hết trường hợp
  • JSON – Muốn xử lý/lưu trữ log, preformated text, ít khi truy vấn.
  • hstore – Có thể xử lý tốt kiểu key/value, tuy nhiên thì JSONB cũng ngon vụ này rồi!

Bạn có đang dùng kiểu dữ liệu schema-less của Postgres không? Bạn dùng nó vào việc gì? Comment bên dưới nha!

(English Version by Craig Kerstiens)

Hoàng Tựa

Yêu thích lập trình web và tạo ra những thứ đẹp đẽ.

Leave a Reply

Your email address will not be published. Required fields are marked *