Phân vùng PostgreSQL cho bảng sự kiện trong audit logging
Phân vùng PostgreSQL cho bảng sự kiện: tìm hiểu khi nào đáng để áp dụng, cách chọn khóa phân vùng, và nó thay đổi gì cho bộ lọc quản trị và retention.

Tại sao bảng sự kiện và audit lại trở thành vấn đề
Bảng sự kiện và bảng audit trông giống nhau, nhưng tồn tại vì những lý do khác nhau.
Bảng sự kiện ghi lại những gì đã xảy ra: lượt xem trang, email đã gửi, webhook được gọi, công việc được chạy. Bảng audit ghi lại ai thay đổi gì và khi nào: thay đổi trạng thái, cập nhật quyền, phê duyệt thanh toán, thường kèm chi tiết “trước” và “sau”.
Cả hai đều tăng nhanh vì là kiểu append-only. Bạn hiếm khi xoá từng hàng, và hàng mới đến liên tục. Thậm chí một sản phẩm nhỏ cũng có thể tạo ra hàng triệu dòng log trong vài tuần khi tính cả công việc nền và tích hợp.
Sự khó chịu xuất hiện trong công việc hàng ngày. Bảng quản trị cần các bộ lọc nhanh như “lỗi trong hôm qua” hoặc “hành động của user này”. Khi bảng lớn lên, những màn hình cơ bản đó bắt đầu chậm.
Bạn thường nhận thấy vài dấu hiệu sau trước tiên:
- Bộ lọc mất vài giây (hoặc timeout) ngay cả với khoảng ngày hẹp.
- Chỉ mục lớn đến mức inserts chậm lại và chi phí lưu trữ tăng.
- VACUUM và autovacuum mất nhiều thời gian hơn, và bạn bắt đầu thấy công việc bảo trì.
- Retention rủi ro: xoá các hàng cũ chậm và tạo bloat.
Phân vùng là một cách để đối phó. Nói đơn giản, nó chia một bảng lớn thành nhiều bảng nhỏ hơn (phân vùng) cùng chia sẻ một tên logic. PostgreSQL điều hướng mỗi dòng mới vào phân vùng thích hợp dựa trên một quy tắc, thường là thời gian.
Đó là lý do các đội cân nhắc phân vùng PostgreSQL cho bảng sự kiện: nó giữ dữ liệu gần đây ở các khối nhỏ hơn, nên PostgreSQL có thể bỏ qua cả những phân vùng nếu một truy vấn chỉ cần một khoảng thời gian.
Phân vùng không phải là công tắc tốc độ thần kỳ. Nó giúp nhiều cho các truy vấn như “7 ngày gần nhất” và làm cho retention đơn giản hơn (drop phân vùng cũ rất nhanh). Nhưng nó cũng có thể tạo vấn đề mới:
- Truy vấn không dùng khóa phân vùng có thể phải kiểm tra nhiều phân vùng.
- Nhiều phân vùng hơn có nghĩa là nhiều đối tượng để quản lý và nhiều cách cấu hình sai.
- Một số ràng buộc unique và chỉ mục trở nên khó áp dụng trên toàn bộ dữ liệu.
Nếu bảng quản trị của bạn phụ thuộc nặng vào bộ lọc theo ngày và quy tắc retention rõ ràng, phân vùng có thể là thắng lợi thực sự. Nếu hầu hết truy vấn là “tìm tất cả hành động của user X trên toàn bộ lịch sử”, nó có thể gây phiền hà trừ khi bạn thiết kế UI và chỉ mục cẩn thận.
Các kiểu truy cập điển hình cho logs và audit
Bảng sự kiện và audit tăng theo một hướng: lên. Chúng nhận luồng inserts ổn định và gần như không cập nhật. Hầu hết dòng được ghi một lần, sau đó được đọc khi support, review sự cố, hoặc kiểm tra tuân thủ.
Hình dạng "append-only" đó quan trọng. Hiệu năng ghi là mối quan tâm liên tục vì inserts diễn ra cả ngày, trong khi hiệu năng đọc quan trọng theo cơn (khi support hoặc ops cần trả lời nhanh).
Hầu hết đọc là các bộ lọc, không phải tra cứu ngẫu nhiên. Trong bảng quản trị, thường bắt đầu rộng (24 giờ gần nhất) rồi thu hẹp theo user, entity, hoặc action.
Các bộ lọc phổ biến bao gồm:
- Một khoảng thời gian
- Một actor (user ID, service account, địa chỉ IP)
- Một target (loại thực thể + ID thực thể, ví dụ Order #1234)
- Một loại hành động (created, updated, deleted, login failed)
- Một trạng thái hoặc mức nghiêm trọng (success/error)
Khoảng thời gian là "lưỡi cắt" tự nhiên vì hầu như luôn có. Đó là nhận xét then chốt đằng sau phân vùng PostgreSQL cho bảng sự kiện: nhiều truy vấn muốn một lát thời gian, và mọi thứ khác là bộ lọc tiếp theo trong lát đó.
Retention là hằng số khác. Logs hiếm khi sống mãi. Đội thường giữ sự kiện chi tiết cao trong 30 hoặc 90 ngày rồi xoá hoặc lưu trữ. Audit logs có thể yêu cầu lâu hơn (365 ngày hoặc hơn), nhưng ngay cả vậy bạn thường muốn cách dự đoán để loại bỏ dữ liệu cũ mà không chặn cơ sở dữ liệu.
Audit logging còn kèm kỳ vọng thêm. Bạn thường muốn lịch sử bất biến, mỗi bản ghi có thể truy vết (ai/cái gì/khi nào cộng ngữ cảnh request hoặc session), và truy cập được kiểm soát (không phải ai cũng nên thấy sự kiện liên quan đến bảo mật).
Những mẫu này xuất hiện trực tiếp trong thiết kế UI. Các bộ lọc người dùng mong đợi theo mặc định - bộ chọn ngày, chọn user, tìm kiếm thực thể, dropdown hành động - chính là các bộ lọc mà bảng và chỉ mục của bạn cần hỗ trợ nếu bạn muốn trải nghiệm quản trị vẫn nhanh khi khối lượng tăng.
Làm sao biết phân vùng có đáng xem xét
Phân vùng không phải best practice mặc định cho audit logs. Nó có lợi khi một bảng trở nên lớn đến mức truy vấn hàng ngày và bảo trì định kỳ bắt đầu va chạm với nhau.
Một gợi ý kích thước đơn giản: khi bảng sự kiện đạt hàng chục triệu dòng, đáng để đo đạc. Khi bảng và chỉ mục đạt vài chục GB, ngay cả tìm kiếm theo khoảng thời gian “đơn giản” cũng có thể chậm hoặc không ổn định vì nhiều trang dữ liệu phải đọc từ đĩa và chỉ mục trở nên tốn kém để duy trì.
Tín hiệu truy vấn rõ ràng nhất là khi bạn thường xuyên yêu cầu một lát thời gian nhỏ (ngày gần nhất, tuần gần nhất), nhưng PostgreSQL vẫn chạm tới phần lớn bảng. Bạn sẽ thấy màn hình “hoạt động gần đây” chậm, hoặc audit lọc theo ngày cộng user, loại hành động, hoặc entity ID. Nếu kế hoạch truy vấn cho thấy quét lớn hoặc buffer reads luôn cao, bạn đang trả tiền cho dữ liệu bạn không định đọc.
Tín hiệu bảo trì cũng quan trọng:
- VACUUM và autovacuum lâu hơn trước kia.
- Autovacuum bị tụt và dead tuples (bloat) tăng.
- Chỉ mục lớn nhanh hơn dự kiến, đặc biệt là chỉ mục nhiều cột.
- Cạnh tranh khóa rõ rệt hơn khi bảo trì trùng với traffic.
Chi phí vận hành là giọt chậm đẩy các đội vào phân vùng. Backup và restore chậm dần khi một bảng lớn lên, lưu trữ tăng, và công việc retention trở nên đắt đỏ vì DELETE lớn tạo bloat và gây thêm công việc vacuum.
Nếu mục tiêu chính là chính sách retention rõ ràng và truy vấn “khoảng thời gian gần đây” nhanh hơn, phân vùng thường đáng cân nhắc. Nếu bảng vừa phải và truy vấn đã nhanh với chỉ mục tốt, phân vùng có thể thêm phức tạp mà không có lợi rõ ràng.
Các lựa chọn phân vùng phù hợp cho bảng sự kiện và audit
Với dữ liệu audit và sự kiện, lựa chọn đơn giản nhất thường là range partition theo thời gian. Logs đến theo thứ tự thời gian, truy vấn thường tập trung vào “24 giờ gần nhất” hoặc “30 ngày gần nhất”, và retention thường theo thời gian. Với phân vùng theo thời gian, xoá dữ liệu cũ có thể đơn giản như loại bỏ phân vùng cũ thay vì chạy DELETE lớn gây bloat.
Phân vùng theo thời gian cũng giữ chỉ mục nhỏ và tập trung hơn. Mỗi phân vùng có chỉ mục riêng, nên truy vấn cho tuần gần nhất không phải đi qua một chỉ mục khổng lồ trải dài nhiều năm.
Các kiểu phân vùng khác tồn tại nhưng phù hợp ít hơn với logs và audit:
- List (theo tenant hoặc khách hàng) có thể hữu dụng khi bạn có vài tenant rất lớn và truy vấn thường nằm trong một tenant. Nó trở nên đau đầu khi có hàng trăm hoặc hàng nghìn tenant.
- Hash (phân đều ghi) có thể giúp khi bạn không có truy vấn theo cửa sổ thời gian và muốn ghi phân bổ đều. Với audit thì ít dùng vì làm cho retention và duyệt theo thời gian khó hơn.
- Subpartitioning (thời gian cộng tenant) có thể mạnh mẽ, nhưng phức tạp tăng nhanh. Chủ yếu dành cho hệ thống rất lớn với nhu cầu cô lập tenant nghiêm ngặt.
Nếu chọn range theo thời gian, hãy chọn kích thước phân vùng phù hợp cách bạn duyệt và lưu trữ dữ liệu. Phân vùng theo ngày hợp lý cho bảng có volume rất cao hoặc retention nghiêm ngặt. Phân vùng theo tháng dễ vận hành ở volume vừa phải.
Ví dụ thực tế: nếu đội admin kiểm tra các lần đăng nhập thất bại mỗi sáng và lọc theo 7 ngày gần nhất, phân vùng theo ngày hoặc tuần khiến truy vấn chỉ chạm vài phân vùng gần nhất. PostgreSQL có thể bỏ qua phần còn lại.
Dù chọn cách nào, hãy lên kế hoạch cho phần tẻ nhạt: tạo phân vùng tương lai, xử lý sự kiện đến muộn, và định nghĩa điều gì xảy ra ở ranh giới (cuối ngày, cuối tháng). Phân vùng có lãi khi những tác vụ đó giữ đơn giản.
Cách chọn khóa phân vùng đúng
Khóa phân vùng tốt khớp với cách bạn đọc bảng, không phải cách dữ liệu trông trên sơ đồ.
Với log và audit, bắt đầu từ bảng quản trị của bạn: người dùng lọc gì đầu tiên, gần như mỗi lần? Với hầu hết đội đó là khoảng thời gian (24 giờ, 7 ngày, ngày tuỳ chỉnh). Nếu đúng vậy, phân vùng theo thời gian thường mang lại lợi ích lớn và dự đoán được vì PostgreSQL có thể bỏ qua toàn bộ phân vùng ngoài phạm vi chọn.
Hãy coi khóa như lời hứa dài hạn. Bạn đang tối ưu cho truy vấn bạn sẽ chạy trong nhiều năm.
Bắt đầu với “bộ lọc đầu tiên” người dùng dùng
Hầu hết màn hình admin theo mẫu: khoảng thời gian + tuỳ chọn user, action, trạng thái, hoặc resource. Phân vùng theo cái thu hẹp kết quả sớm và nhất quán.
Một kiểm tra hiện thực nhanh:
- Nếu view mặc định là “sự kiện gần đây”, phân vùng theo timestamp.
- Nếu view mặc định là “sự kiện cho một tenant/account”,
tenant_idcó thể hợp lý, nhưng chỉ khi tenant đủ lớn để biện minh. - Nếu bước đầu luôn là “chọn user”,
user_idnghe hấp dẫn nhưng thường tạo quá nhiều phân vùng để quản lý.
Tránh khóa có độ phân mảnh cao
Phân vùng hiệu quả nhất khi mỗi phân vùng là một khối dữ liệu có ý nghĩa. Các khóa như user_id, session_id, request_id, hoặc device_id có thể dẫn tới hàng nghìn hoặc hàng triệu phân vùng. Điều đó tăng overhead metadata, làm bảo trì phức tạp, và thường làm planner chậm.
Phân vùng theo thời gian giữ số phân vùng dự đoán được. Bạn chọn theo ngày/tuần/tháng tùy volume. Quá ít phân vùng (một mỗi năm) không giúp nhiều. Quá nhiều (một mỗi giờ) nhanh chóng tăng overhead.
Chọn timestamp phù hợp: created_at hay occurred_at
Rõ ràng về ý nghĩa thời gian:
- occurred_at: khi sự kiện thực sự xảy ra trong sản phẩm.
- created_at: khi cơ sở dữ liệu ghi nhận nó.
Với audit, “occurred” thường là cái admin quan tâm. Nhưng giao hàng muộn (mobile offline, retry, queue) nghĩa là occurred_at có thể đến trễ. Nếu sự kiện đến muộn thường xuyên, phân vùng theo created_at và tạo chỉ mục trên occurred_at để lọc có thể ổn định về mặt vận hành hơn. Lựa chọn khác là định nghĩa chính sách backfill rõ ràng và chấp nhận rằng phân vùng cũ đôi khi sẽ nhận sự kiện muộn.
Cũng quyết định cách lưu thời gian. Dùng kiểu nhất quán (thường timestamptz) và coi UTC là nguồn chân lý. Hiển thị theo timezone người xem trong UI. Điều đó giữ ranh giới phân vùng ổn định và tránh rắc rối với daylight saving.
Từng bước: lập kế hoạch và triển khai phân vùng
Phân vùng dễ nhất khi bạn coi nó như một dự án migration nhỏ, không phải tinh chỉnh vội. Mục tiêu là ghi đơn giản, đọc dự đoán được, và retention trở thành thao tác thường quy.
Kế hoạch triển khai thực tế
-
Chọn kích thước phân vùng phù hợp với volume. Phân vùng theo tháng thường ổn ở vài trăm nghìn dòng mỗi tháng. Nếu bạn insert hàng chục triệu mỗi tháng, phân vùng theo tuần hoặc ngày giữ chỉ mục nhỏ hơn và công việc vacuum dễ quản lý hơn.
-
Thiết kế khóa và ràng buộc cho bảng phân vùng. Trong PostgreSQL, ràng buộc unique phải bao gồm khóa phân vùng (hoặc được thực thi theo cách khác). Mẫu phổ biến là
(created_at, id), trong đóidđược sinh vàcreated_atlà khóa phân vùng. Điều này tránh bất ngờ sau này khi bạn nhận ra ràng buộc mong đợi không được cho phép. -
Tạo phân vùng tương lai trước khi cần. Đừng đợi inserts fail vì không có phân vùng phù hợp. Quyết định tạo trước bao lâu (ví dụ 2-3 tháng) và làm đó thành công việc định kỳ.
-
Giữ chỉ mục mỗi phân vùng nhỏ và có chủ đích. Phân vùng không làm chỉ mục miễn phí. Hầu hết bảng sự kiện cần khóa phân vùng cộng 1-2 chỉ mục phù hợp với bộ lọc admin thực tế, như
actor_id,entity_id, hoặcevent_type. Bỏ qua chỉ mục “phòng hờ”. Bạn có thể thêm sau cho các phân vùng mới và backfill cho phân vùng cũ nếu cần. -
Lập retention xoay quanh việc drop phân vùng, không xóa từng hàng. Nếu bạn giữ 180 ngày, drop phân vùng cũ là nhanh và tránh deletes lớn sinh bloat. Ghi rõ quy tắc retention, ai chạy nó, và cách xác minh hoạt động.
Ví dụ nhỏ
Nếu bảng audit của bạn nhận 5 triệu dòng mỗi tuần, phân vùng theo tuần trên created_at là khởi đầu hợp lý. Tạo phân vùng trước 8 tuần và giữ hai chỉ mục mỗi phân vùng: một cho tìm kiếm phổ biến theo actor_id và một cho entity_id. Khi cửa sổ retention kết thúc, drop phân vùng tuần cũ thay vì xóa hàng triệu dòng.
Nếu bạn xây công cụ nội bộ bằng AppMaster, tốt khi quyết định khóa phân vùng và ràng buộc sớm để mô hình dữ liệu và mã sinh theo cùng giả định từ đầu.
Phân vùng thay đổi gì cho bộ lọc bảng quản trị
Khi bạn phân vùng bảng log, bộ lọc trên giao diện quản trị không còn là “chỉ UI”. Chúng trở thành yếu tố chính quyết định truy vấn chạm vào vài phân vùng hay quét cả tháng dữ liệu.
Sự thay đổi thực tế lớn nhất: thời gian không còn là tuỳ chọn nữa. Nếu người dùng có thể chạy tìm kiếm không giới hạn (không có khoảng ngày, chỉ “hiện tất cả cho user X”), PostgreSQL có thể phải kiểm tra mọi phân vùng. Dù mỗi kiểm tra nhanh, mở nhiều phân vùng tạo overhead và trang sẽ chậm.
Một quy tắc hiệu quả: yêu cầu khoảng thời gian cho tìm kiếm log và audit, mặc định hợp lý (ví dụ last 24 hours). Nếu ai đó thực sự cần “tất cả thời gian”, làm đó là lựa chọn có chủ ý và cảnh báo rằng kết quả có thể chậm.
Làm cho bộ lọc phù hợp với partition pruning
Partition pruning chỉ có ích khi mệnh đề WHERE bao gồm khóa phân vùng ở dạng PostgreSQL có thể dùng. Các bộ lọc như created_at BETWEEN X AND Y prune tốt. Các mẫu thường phá pruning bao gồm chuyển kiểu timestamp sang date, bọc cột trong hàm, hoặc lọc chủ yếu trên trường thời gian khác với khóa phân vùng.
Bên trong mỗi phân vùng, chỉ mục nên phù hợp với cách người dùng thực sự lọc. Thực tế, các tổ hợp thường quan trọng là thời gian cộng một điều kiện khác: tenant/workspace, user, action/type, entity ID, hoặc status.
Sắp xếp và phân trang: giữ nông
Phân vùng không sửa phân trang chậm tự thân. Nếu admin panel sắp xếp theo mới nhất và người dùng nhảy tới trang 5000, pagination với OFFSET sâu vẫn bắt PostgreSQL phải bỏ qua nhiều dòng. Phân trang theo con trỏ thường tốt hơn cho logs: “load events before this timestamp/id.” Cách này giữ DB dùng chỉ mục thay vì bỏ qua các offset lớn.
Các preset cũng hữu ích. Một vài tuỳ chọn thường đủ: last 24 hours, last 7 days, today, yesterday, custom range. Preset giảm khả năng “scan mọi thứ” vô tình và làm trải nghiệm admin dự đoán hơn.
Những sai lầm và bẫy thường gặp
Hầu hết dự án phân vùng thất bại vì lý do đơn giản: phân vùng hoạt động, nhưng truy vấn và UI không khớp với nó. Nếu muốn phân vùng có lợi, hãy thiết kế quanh bộ lọc thực tế và retention.
1) Phân vùng theo cột thời gian sai
Partition pruning chỉ xảy ra khi WHERE khớp khóa phân vùng. Sai lầm phổ biến là phân vùng theo created_at trong khi admin panel lọc theo event_time (hoặc ngược lại). Nếu support luôn hỏi “cái gì diễn ra giữa 10:00 và 10:15”, nhưng bảng phân vùng theo thời gian ingest, bạn vẫn có thể chạm nhiều dữ liệu hơn mong muốn.
2) Tạo quá nhiều phân vùng nhỏ
Phân vùng theo giờ (hoặc nhỏ hơn) trông gọn, nhưng tăng overhead: nhiều đối tượng để quản lý, planner phức tạp hơn, và khả năng thiếu chỉ mục hoặc phân quyền không đồng nhất.
Trừ khi bạn có volume viết cực lớn và retention nghiêm ngặt, phân vùng theo ngày hoặc tháng thường dễ vận hành hơn.
3) Giả sử "duy nhất toàn cục" vẫn hoạt động
Bảng phân vùng có giới hạn: một số chỉ mục unique phải bao gồm khóa phân vùng, nếu không PostgreSQL không thể thi hành trên tất cả phân vùng. Điều này thường khiến đội ngạc nhiên khi họ mong event_id là duy nhất mãi mãi. Nếu cần ID duy nhất, dùng UUID và đảm bảo duy nhất cùng với khóa thời gian, hoặc thực thi ở tầng ứng dụng.
4) Để UI admin chạy tìm kiếm mở rộng tự do
Admin panel thường có ô tìm kiếm thân thiện chạy không cần bộ lọc. Trên bảng phân vùng, điều đó có thể nghĩa là quét mọi phân vùng.
Tìm kiếm full-text trên payload đặc biệt rủi ro. Thêm rào chắn: yêu cầu khoảng thời gian, giới hạn khoảng mặc định, và đặt “all time” là lựa chọn có chủ ý.
5) Không có kế hoạch retention (và không có kế hoạch cho phân vùng)
Phân vùng không tự động giải quyết retention. Không có chính sách, bạn sẽ có núi phân vùng cũ, lưu trữ bừa bãi, và bảo trì chậm.
Một bộ quy tắc vận hành đơn giản thường ngăn được điều này: định nghĩa thời gian giữ raw events, tự động tạo phân vùng tương lai và drop cũ theo lịch, áp chỉ mục đồng đều, giám sát số phân vùng và ngày biên, và test các bộ lọc chậm nhất với volume dữ liệu thực tế.
Checklist nhanh trước khi quyết
Phân vùng có thể là thắng lợi lớn cho audit logs, nhưng nó thêm công việc định kỳ. Trước khi thay đổi schema, kiểm tra kỹ cách người dùng thực sự dùng bảng.
Nếu nỗi đau chính là trang quản trị timeout khi ai đó mở “Last 24 hours” hoặc “This week”, bạn gần với một lựa chọn hợp lý. Nếu hầu hết truy vấn là “user ID trên toàn lịch sử”, phân vùng có thể ít giúp hơn trừ khi bạn thay đổi cách UI hướng dẫn tìm kiếm.
Một checklist ngắn giữ đội trung thực:
- Khoảng thời gian là bộ lọc mặc định. Hầu hết truy vấn admin bao gồm cửa sổ rõ ràng (từ/đến). Nếu tìm kiếm mở là phổ biến, partition pruning giúp ít hơn.
- Retention thi hành bằng cách drop phân vùng, không xóa hàng. Bạn sẵn sàng drop phân vùng cũ và có luật rõ ràng về thời gian giữ.
- Số phân vùng duy trì hợp lý. ước tính phân vùng mỗi năm (hàng ngày, hàng tuần, hàng tháng). Quá nhiều phân vùng nhỏ tăng overhead. Quá ít làm giảm lợi ích.
- Chỉ mục khớp bộ lọc thực tế. Ngoài khóa phân vùng, bạn vẫn cần chỉ mục trên mỗi phân vùng cho các bộ lọc phổ biến và thứ tự trả về.
- Phân vùng được tạo tự động và giám sát. Có job định kỳ tạo phân vùng tương lai, và bạn biết khi nó thất bại.
Một kiểm tra thực tế: xem ba bộ lọc mà nhóm support hoặc ops dùng nhiều nhất. Nếu hai trong ba thường được thỏa mãn bởi “khoảng thời gian + một điều kiện khác”, phân vùng PostgreSQL cho bảng sự kiện thường đáng cân nhắc.
Ví dụ thực tế và bước tiếp theo khả thi
Một đội support mở hai màn hình suốt ngày: “Login events” (đăng nhập thành công và thất bại) và “Security audits” (reset mật khẩu, đổi role, cập nhật API key). Khi khách hàng báo hoạt động đáng ngờ, đội lọc theo user, kiểm tra vài giờ gần nhất, và xuất báo cáo ngắn.
Trước khi phân vùng, mọi thứ nằm trong một bảng events lớn. Nó tăng nhanh, và ngay cả tìm kiếm đơn giản cũng bắt đầu chậm vì DB phải đi qua nhiều dòng cũ. Retention cũng đau: job đêm xoá hàng cũ nhưng DELETE lớn lâu, tạo bloat, và cạnh tranh với traffic bình thường.
Sau khi phân vùng theo tháng (dùng timestamp sự kiện), workflow cải thiện. Bảng quản trị yêu cầu bộ lọc thời gian, nên hầu hết truy vấn chỉ chạm một hoặc hai phân vùng. Trang tải nhanh hơn vì PostgreSQL có thể bỏ qua phân vùng ngoài phạm vi. Retention trở thành thao tác định kỳ: thay vì xóa hàng triệu dòng, bạn drop phân vùng cũ.
Một điều vẫn khó: tìm kiếm full-text “toàn thời gian”. Nếu ai đó tìm IP hoặc cụm từ mơ hồ không giới hạn ngày, phân vùng không làm nó rẻ. Sửa thường ở phía sản phẩm: mặc định tìm kiếm về một cửa sổ thời gian và làm “24 giờ / 7 ngày / 30 ngày” là đường dẫn hiển nhiên.
Các bước tiếp theo thực tế thường có hiệu quả:
- Lập bản đồ bộ lọc admin trước. Ghi lại trường nào người dùng dùng và trường nào cần bắt buộc.
- Chọn phân vùng phù hợp với cách bạn duyệt. Phân vùng theo tháng thường là khởi đầu tốt; chỉ chuyển sang tuần khi volume bắt buộc.
- Đặt khoảng thời gian là bộ lọc hàng đầu. Nếu UI cho phép “no date”, hãy chờ trang chậm.
- Đồng bộ chỉ mục với bộ lọc thực tế. Khi thời gian luôn có mặt, chiến lược chỉ mục ưu tiên theo thời gian thường là baseline đúng.
- Thiết lập luật retention khớp ranh giới phân vùng (ví dụ giữ 13 tháng và drop cũ hơn).
Nếu bạn xây bảng quản trị nội bộ với AppMaster (appmaster.io), đáng để mô hình các giả định này sớm: coi bộ lọc có giới hạn thời gian là một phần của mô hình dữ liệu, không chỉ lựa chọn UI. Quyết định nhỏ đó bảo vệ hiệu năng truy vấn khi khối lượng log tăng.
Câu hỏi thường gặp
Phân vùng hữu ích nhất khi các truy vấn phổ biến của bạn có giới hạn thời gian rõ ràng (ví dụ: “last 24 hours” hoặc “last 7 days”) và bảng đã đủ lớn khiến chỉ mục và công việc bảo trì gây khó chịu. Nếu truy vấn chính của bạn là “toàn bộ lịch sử cho user X”, phân vùng có thể tăng chi phí trừ khi bạn buộc bộ lọc thời gian ở UI và thêm các chỉ mục phù hợp cho từng phân vùng.
Range partitioning theo thời gian thường là lựa chọn mặc định tốt nhất cho logs và audit vì ghi đến theo thứ tự thời gian, truy vấn thường bắt đầu bằng một cửa sổ thời gian, và retention thường dựa trên thời gian. List hoặc hash có thể phù hợp trong vài trường hợp đặc thù, nhưng chúng thường làm cho việc duyệt và quản lý retention khó khăn hơn cho workflow kiểu audit.
Chọn trường mà người dùng lọc trước tiên và gần như luôn luôn. Trong hầu hết admin panel đó là khoảng thời gian (timestamp), nên phân vùng theo thời gian là lựa chọn dễ dự đoán nhất. Hãy coi đây là cam kết dài hạn, vì thay đổi khóa phân vùng sau này là một migration thực thụ.
Dùng các khóa như timestamp hoặc tenant chỉ khi chúng tạo ra số phân vùng quản lý được. Tránh các khóa có độ phân mảnh cao như user_id, session_id hoặc request_id vì chúng có thể tạo ra hàng nghìn phân vùng, tăng chi phí cho planner và vận hành mà không mang lại lợi ích ổn định.
Partition theo created_at khi bạn cần ổn định vận hành và không thể tin tưởng các bản ghi đến muộn (queue, retry, client offline). Partition theo occurred_at khi trường thời gian sự kiện là đáng tin cậy và trường hợp sử dụng chính là “cái gì đã xảy ra trong khoảng này”. Một thoả hiệp phổ biến là phân vùng theo created_at và thêm chỉ mục trên occurred_at để lọc.
Có. Hầu hết admin panel nên yêu cầu khoảng thời gian sau khi bảng được phân vùng. Không có bộ lọc thời gian, PostgreSQL có thể phải kiểm tra nhiều hoặc tất cả phân vùng, khiến trang chậm dù mỗi phân vùng nhanh. Một giá trị mặc định tốt là “last 24 hours”, còn “all time” là một lựa chọn có chủ ý.
Có. Bao bọc khóa phân vùng trong hàm (ví dụ cast sang date) có thể ngăn pruning, và lọc theo cột thời gian khác với khóa phân vùng có thể buộc phải quét thêm phân vùng. Giữ điều kiện ở dạng đơn giản như created_at BETWEEN X AND Y để pruning hoạt động ổn định.
Tránh pagination với OFFSET sâu cho views log vì nó bắt PostgreSQL phải bỏ qua nhiều dòng. Dùng phân trang theo con trỏ thay vào đó, ví dụ “load events before this (timestamp, id)”, cách này tận dụng chỉ mục và giữ hiệu năng ổn định khi bảng lớn lên.
Trong PostgreSQL, một số ràng buộc unique trên bảng phân vùng phải bao gồm khóa phân vùng, nên ràng buộc id toàn cục có thể không hoạt động như mong đợi. Một mẫu thực tế là sự duy nhất tổ hợp như (created_at, id) khi created_at là khóa phân vùng. Nếu cần ID duy nhất cho bên ngoài, giữ UUID và xử lý tính duy nhất toàn cục cẩn thận.
Drop (xoá) các phân vùng cũ là nhanh và tránh bloat cùng công việc VACUUM do DELETE lớn gây ra. Chìa khoá là căn chỉnh luật retention với ranh giới phân vùng và tự động hoá: tạo phân vùng tương lai trước và xoá những phân vùng hết hạn theo lịch. Không có tự động hoá, phân vùng sẽ thành công việc thủ công tốn thời gian.


