Có 2 phần cho câu hỏi của tôi.
- Có cách nào để chỉ định kích thước ban đầu của cơ sở dữ liệu trong PostgreSQL không?
- Nếu không có, làm thế nào để bạn đối phó với sự phân mảnh khi cơ sở dữ liệu phát triển theo thời gian?
Gần đây tôi đã di chuyển từ MSSQL sang Postgres và một trong những điều chúng tôi đã làm trong thế giới MSSQL khi tạo cơ sở dữ liệu là chỉ định kích thước ban đầu của cơ sở dữ liệu và nhật ký giao dịch. Điều này làm giảm sự phân mảnh và tăng hiệu suất, đặc biệt là nếu biết trước kích thước "bình thường" của cơ sở dữ liệu.
Hiệu suất của cơ sở dữ liệu của tôi giảm khi kích thước tăng lên. Ví dụ, khối lượng công việc tôi đặt nó thông thường mất 10 phút. Khi cơ sở dữ liệu phát triển, thời gian này tăng lên. Làm một VACUUM, VACUUM FULL và VACUUM FULL ANALYZE không xuất hiện để giải quyết vấn đề. Điều gì giải quyết vấn đề hiệu năng là dừng cơ sở dữ liệu, phân mảnh ổ đĩa và sau đó thực hiện VACUUM FULL ANALYZE đưa hiệu năng kiểm tra của tôi trở lại 10 phút ban đầu. Điều này khiến tôi nghi ngờ rằng sự phân mảnh là điều khiến tôi đau đớn.
Tôi không thể tìm thấy bất kỳ tham chiếu nào để đặt trước không gian bảng / không gian cơ sở dữ liệu trong Postgres. Hoặc là tôi đang sử dụng thuật ngữ sai và do đó không tìm thấy gì, hoặc có một cách khác để giảm thiểu sự phân mảnh hệ thống tệp trong Postgres.
Bất kỳ con trỏ?
Giải pháp
Các câu trả lời được cung cấp đã giúp xác nhận những gì tôi bắt đầu nghi ngờ. PostgreSQL lưu trữ cơ sở dữ liệu trên nhiều tệp và đây là những gì cho phép cơ sở dữ liệu phát triển mà không lo bị phân mảnh. Hành vi mặc định là đóng gói các tệp này vào vành với dữ liệu bảng, điều này tốt cho các bảng hiếm khi thay đổi nhưng lại không tốt cho các bảng được cập nhật thường xuyên.
PostgreSQL sử dụng MVCC để cung cấp quyền truy cập đồng thời vào dữ liệu bảng. Theo sơ đồ này, mỗi bản cập nhật tạo ra một phiên bản mới của hàng đã được cập nhật (điều này có thể thông qua dấu thời gian hoặc số phiên bản, ai biết?). Dữ liệu cũ không bị xóa ngay lập tức, nhưng được đánh dấu để xóa. Việc xóa thực tế xảy ra khi một thao tác VACUUM được thực hiện.
Làm thế nào điều này liên quan đến các yếu tố điền? Hệ số điền mặc định của bảng là 100 gói đầy đủ các trang bảng, điều này có nghĩa là không có khoảng trống trong trang bảng để giữ các hàng được cập nhật, tức là các hàng được cập nhật sẽ được đặt trong một trang bảng khác với hàng ban đầu. Điều này là xấu cho hiệu suất, như kinh nghiệm của tôi cho thấy. Vì các bảng tóm tắt của tôi được cập nhật rất thường xuyên (tối đa 1500 hàng / giây), tôi đã chọn đặt hệ số lấp đầy là 20, tức là 20% bảng sẽ dành cho dữ liệu hàng được chèn và 80% cho dữ liệu cập nhật. Mặc dù điều này có vẻ quá mức, nhưng không gian lớn dành cho các hàng được cập nhật có nghĩa là các hàng được cập nhật vẫn ở trong cùng một trang với bản gốc và có một trang bảng không đầy đủ vào thời điểm trình nền tự động chạy để xóa các hàng lỗi thời.
Để "sửa" cơ sở dữ liệu của tôi, tôi đã làm như sau.
- Đặt hệ số lấp đầy của các bảng tóm tắt của tôi thành 20. Bạn có thể thực hiện việc này tại thời điểm tạo bằng cách chuyển một tham số cho CREATE TABLE hoặc sau thực tế thông qua ALTER TABLE. Tôi đã ban hành lệnh plpgsql sau đây:
ALTER TABLE "my_summary_table" SET (fillfactor = 20);
- Đã phát hành VACUUM FULL, vì điều này viết một phiên bản hoàn toàn mới của tệp bảng và do đó bằng cách ghi một tệp bảng mới với hệ số điền mới .
Chạy lại các thử nghiệm của tôi, tôi thấy không có sự suy giảm hiệu năng ngay cả khi cơ sở dữ liệu lớn như tôi cần với hàng triệu hàng.
TL; DR - Phân mảnh tệp không phải là nguyên nhân, đó là phân mảnh không gian bảng. Điều này được giảm nhẹ bằng cách điều chỉnh hệ số lấp đầy của bảng cho phù hợp với trường hợp sử dụng cụ thể của bạn.