Computer >> Máy Tính >  >> Lập trình >> Ruby

Quản lý các bảng được phân vùng PostgreSQL bằng Ruby

Chúng tôi sử dụng các bảng được phân vùng trong cơ sở dữ liệu PostgreSQL chính của mình để làm hết hạn hiệu quả dữ liệu cũ, vì việc xóa một loạt dữ liệu khỏi một bảng lớn có thể khiến hiệu suất cơ sở dữ liệu bị ảnh hưởng. Trước phiên bản 10, PostgreSQL không có hỗ trợ gốc cho các bảng được phân vùng, vì vậy chúng tôi đã sử dụng phần mở rộng pg_partman để triển khai phân vùng. Nó hoạt động bằng cách sử dụng kế thừa bảng của PostgreSQL để tạo các bảng con của bảng được phân vùng và kích hoạt để chèn dữ liệu vào các bảng con chứ không phải bảng cha. Tiện ích mở rộng đó đã hoạt động tốt đối với chúng tôi, nhưng nó có một nhược điểm - nó không phải là một tùy chọn khi bạn đang sử dụng Amazon RDS, vì nó không được hỗ trợ. Bây giờ PostgreSQL đã hỗ trợ cho các phân vùng gốc, tôi đã nghĩ rằng bây giờ là lúc để xem về việc loại bỏ tiện ích mở rộng đó để chúng tôi có tùy chọn sử dụng RDS.

Trường hợp sử dụng phân vùng của chúng tôi khá đơn giản:chúng tôi phân vùng các bảng dựa trên thời gian, tạo một phân vùng mới cho mỗi ngày, tuần hoặc tháng, tùy thuộc vào số hàng chúng ta muốn lưu trữ trên tất cả các phân vùng và thời gian chúng ta muốn giữ lại dữ liệu. Tất cả các bảng được phân vùng của chúng tôi đều có created_at cột sẽ được sử dụng để xác định phân vùng nào lưu trữ mỗi hàng. Ví dụ:chúng ta có thể có một bảng được định nghĩa như sau:

create table events (
  project_id integer,
  data jsonb,
  created_at timestamp
)
partition by range (created_at);

Và nếu chúng ta muốn có các phân vùng hàng tuần, chúng sẽ trông như thế này:

create table events_p2019_10_28 partition of events for values from ('2019-10-28') to ('2019-11-04');
create table events_p2019_11_04 partition of events for values from ('2019-11-04') to ('2019-11-11');

Với sơ đồ phân vùng dựa trên thời gian, việc xóa dữ liệu cũ đơn giản như bỏ một trong các phân vùng. Sau đó, việc bảo trì thường xuyên mà chúng ta cần làm là tạo các phân vùng mới cho các phạm vi ngày khi chúng ta tiếp cận chúng và xóa các phân vùng cũ chứa dữ liệu mà chúng ta không còn muốn nữa. Để làm cho việc bảo trì đó dễ dàng hơn một chút, tôi đã tạo viên ngọc pg_partition_manager. Đương nhiên, nó được lấy cảm hứng từ trải nghiệm của tôi với tiện ích mở rộng pg_partman, tiện ích này đã phục vụ chúng tôi rất tốt.

Hãy xem cách bạn sử dụng gem này, dựa trên bảng sự kiện và lược đồ phân vùng được mô tả ở trên. Bạn sẽ tạo một tập lệnh hoặc tác vụ cào giống như sau:

require "pg_partition_manager"

PgPartitionManager::Time.process([{parent_table: "public.events", period: "week", premake: 1, retain: 3}])

parent_table được định nghĩa là schema.table_name (public , lược đồ mặc định, thường là lược đồ duy nhất mà các nhà phát triển Rails sử dụng). period có thể là ngày, tuần hoặc tháng. Bạn có thể chọn số lượng bảng bạn muốn tạo trước (sau khoảng thời gian hiện tại) với premake và có bao nhiêu bảng bạn muốn giữ lại (trước khoảng thời gian hiện tại) với retain . Đá quý mặc định tạo trước 4 bảng nếu bạn không chỉ định premake và nó được mặc định giữ lại dữ liệu trong 7 ngày, 4 tuần và 6 tháng nếu bạn không chỉ định retain .

Gọi tập lệnh / nhiệm vụ đó với một công việc cron hàng ngày và bạn đã sẵn sàng - nó sẽ tạo và thả các bảng khi cần thiết.

Tất cả các truy vấn ActiveRecord hoạt động giống như chúng sẽ làm với một bảng không được phân vùng, vì vậy bạn không cần phải thay đổi gì trong mã của mình. Đó là, Event.create , Event.where , v.v., sẽ hoạt động như mọi khi, với việc PostgreSQL đưa dữ liệu vào đúng phân vùng cho bạn khi bạn chèn nó. Tuy nhiên, có một thay đổi mà bạn có thể nhận thấy nếu bạn có nhiều dữ liệu ... khi bạn bao gồm created_at trong các truy vấn của bạn, PostgreSQL sẽ không phải quét tất cả các phân vùng - chỉ những phân vùng bao gồm phạm vi bạn chỉ định trong mệnh đề where của mình.

Tóm lại, nếu bạn có nhiều dữ liệu theo thời gian mà bạn muốn xóa khi nó hết hạn, hãy sử dụng các bảng được phân vùng PostgreSQL và đá quý pg_partition_manager để làm cho ứng dụng của bạn hài lòng. :)