1 điểm bởi GN⁺ 2024-02-18 | 1 bình luận | Chia sẻ qua WhatsApp

Ghi chú của tôi về thiết kế schema Postgres của GitLab

  • Bằng cách xem xét schema Postgres của GitLab, tôi muốn so sánh với schema mình đang thiết kế và học các thực hành tốt nhất từ định nghĩa schema của GitLab.
  • GitLab là nền tảng DevOps mã nguồn mở, là đối thủ thay thế cho GitHub và có thể tự host.

Sử dụng loại khóa chính phù hợp

  • Khi cơ sở dữ liệu còn nhỏ thì khó thấy, nhưng khi mở rộng, khóa chính ảnh hưởng đến dung lượng lưu trữ, tốc độ ghi và tốc độ đọc.
  • Trong 573 bảng, GitLab dùng kiểu khóa chính bigserial cho 380 bảng, dùng serial4 cho 170 bảng và phần còn lại 23 bảng dùng khóa chính tổng hợp.

Sử dụng ID nội bộ và ID bên ngoài

  • Việc không phơi bày khóa chính ra thế giới bên ngoài là một thực hành tốt.
  • GitLab sử dụng cả ID nội bộ (id) và ID bên ngoài (iid) trong các bảng như issues, ci_pipelines, deployments, epics.

Sử dụng kiểu dữ liệu text và ràng buộc kiểm tra

  • Schema của GitLab dùng cả character varying(n)text, nhưng sử dụng kiểu text thường xuyên hơn.
  • Kiểu text không có ràng buộc độ dài, và GitLab định nghĩa ràng buộc độ dài bằng cách sử dụng CHECK.

Quy tắc đặt tên

  • Tất cả các bảng đều dùng số nhiều, và tiền tố tên module được dùng để tạo không gian tên.
  • Tên bảng và cột tuân theo quy tắc snake_case.

Sử dụng múi giờ cho timestamp

  • GitLab sử dụng cả timestamp with timezonetimestamp without timezone.
  • Đối với tác vụ hệ thống, GitLab dùng timestamp without timezone; đối với tác vụ của người dùng thì dùng timestamp with timezone.

Ràng buộc khóa ngoại

  • GitLab sử dụng ràng buộc khóa ngoại cho hầu hết các bảng, nhưng không dùng trong một số bảng như audit_events, abuse_reports, web_hooks_logs, spam_logs.

Phân vùng các bảng lớn

  • GitLab phân vùng các bảng có thể có dung lượng lớn để tăng hiệu năng truy vấn.

Hỗ trợ trường hợp sử dụng tìm kiếm LIKE bằng Trigram và gin_trgm_ops

  • GitLab sử dụng chỉ mục GIN (Generalized Inverted Index) để thực hiện tìm kiếm hiệu quả.

Sử dụng jsonb

  • Schema của GitLab sử dụng kiểu dữ liệu jsonb trong nhiều bảng.

Các mẹo khác

  • Sử dụng trường kiểm toán như updated_at trong các bảng có thể chỉnh sửa, và không sử dụng trong các bảng log không thể chỉnh sửa.
  • Enums được lưu bằng smallint thay vì character varying, giúp tiết kiệm dung lượng.

Nhận xét của GN⁺:

  • Thiết kế schema của GitLab cung cấp cái nhìn sâu sắc về thiết kế cơ sở dữ liệu, đặc biệt là các bài học quan trọng về tối ưu hóa schema cho hệ thống quy mô lớn.
  • Vì GitLab là mã nguồn mở, các quyết định thiết kế schema như vậy mang lại ví dụ thực tế để các nhà phát triển khác áp dụng cho dự án của mình.
  • Điều có thể học được từ schema của GitLab là cần cân nhắc kỹ các yếu tố ảnh hưởng lớn đến hiệu năng và bảo trì cơ sở dữ liệu như chọn kiểu dữ liệu, chiến lược lập chỉ mục, phân vùng và việc sử dụng ràng buộc khóa ngoại.

1 bình luận

 
GN⁺ 2024-02-18
Ý kiến trên Hacker News
  • Không nên phơi bày khóa chính ra bên ngoài là một thực hành tốt theo chuẩn. Đặc biệt quan trọng khi dùng khóa chính tự tăng tuần tự kiểu integer hoặc bigint, vì chúng có thể đoán trước.

    • Ý kiến cho rằng việc không phơi bày khóa chính ra bên ngoài là một thực hành tốt. Đặc biệt khi khóa nhận dạng tăng dần theo thứ tự thì càng quan trọng hơn vì chúng có thể bị đoán trước.
  • Ví dụ, GitHub đã có 128 triệu kho lưu trữ công khai vào năm 2020. Nếu giả sử mỗi kho có 20 issue thì phạm vi serial sẽ bị vượt quá. Ngoài ra, việc thay đổi kiểu của bảng rất tốn kém.

    • Họ nêu ví dụ số lượng kho lưu trữ công khai của GitHub vào năm 2020 và số lượng issue dự kiến để chỉ ra rằng phạm vi serial có thể bị vượt qua, đồng thời nhắc đến chi phí cao của việc đổi kiểu bảng.
  • Lập luận về dung lượng lưu trữ của cột UUID không thuyết phục. Khi bảng có thêm 5 cột khác thì chênh lệch giữa 128-bit và 64-bit không phải là lớn.

    • Họ cho rằng điều quan trọng hơn vấn đề dung lượng lưu trữ là hiệu năng. Vì UUIDv4 là ngẫu nhiên hoàn toàn nên không tối ưu cho hiệu năng chỉ mục, và UUIDv7 có thể là một giải pháp tốt hơn.
  • Rằng khóa ngoại là đắt đỏ là lập luận thường được lặp đi lặp lại, nhưng gần như chưa được kiểm chứng. Việc tận dụng cơ sở dữ liệu đòi hỏi kiến thức và thử nghiệm, và thường mang lại kết quả tốt hơn việc tái triển khai từ đầu.

    • Ý kiến này đặt câu hỏi về luận điểm phổ biến rằng khóa ngoại tốn kém, đồng thời nhấn mạnh tầm quan trọng của việc sử dụng cơ sở dữ liệu đúng cách.
  • Tôi tự hỏi liệu có ai đã viết về sự khác biệt về hiệu năng giữa Gitlab và Github chưa.

    • Họ bày tỏ sự quan tâm đến sự khác biệt hiệu năng giữa Gitlab và Github, và cảm thấy thời gian tải trang của Gitlab chậm hơn rất nhiều so với GitHub.
  • Tôi từng thắc mắc vì sao chữ I được thêm vào biến CI CI_PIPELINE_IIDCI_MERGE_REQUEST_IID. Ban đầu tôi đoán đây là lựa chọn liên quan đến cơ sở dữ liệu, và bài viết này đã xác nhận điều đó.

    • Họ đặt câu hỏi về mục đích thêm I trong các biến CI này, và hiểu rằng đây là lựa chọn liên quan tới cơ sở dữ liệu.
  • Bài này rất hữu ích. Tôi tò mò không biết có thể tìm các bài tương tự ở đâu.

    • Họ cho rằng bài này rất hữu ích và muốn tìm nguồn bài viết tương tự.
  • Có phải chỉ có tôi cho rằng thiết kế schema và phát triển đã đi sau thời đại không?

    • Họ cảm thấy thiết kế schema và phát triển còn lỗi thời, đặc biệt lo ngại nguy cơ mất dữ liệu khi thực hiện di trú dữ liệu. Họ đặt câu hỏi về việc DB/ORM không tự động xử lý ID bên ngoài và ID bên trong.
  • 1경 tương đương với 1000000000조.

    • Họ chỉ ra thực tế phải chọn giữa số nguyên 32-bit và 64-bit, và nhắc tới nhu cầu một kiểu số nguyên 5 byte để hỗ trợ độ lớn xấp xỉ 1조.
  • Khi dùng kiểu UUID v4 bản địa của Postgres, kích thước bảng tăng 25% và tốc độ chèn giảm còn 25% so với bigserial.

    • Họ tò mò về sự khác biệt hiệu năng giữa UUIDv4 và bigserial, và hỏi tại sao UUIDv4 lại có hiệu năng kém hơn.