Cách làm Postgres chậm đi
(byteofdev.com)- Giới thiệu cách tiếp cận mang tính thử nghiệm về tổ hợp tham số có thể làm suy giảm hiệu năng Postgres một cách cực đoan
- Thực hiện tinh chỉnh ngược các yếu tố như bộ đệm, chỉ mục, WAL, I/O vốn thường được tối ưu để tăng tốc
- Thao tác cực đoan với shared_buffers, autovacuum và các tùy chọn liên quan đến WAL để đạt mức giảm TPS tới 42.000 lần
- Áp dụng cả các tính năng mới như io_method và io_workers của Postgres 18/19 để thử nghiệm giới hạn I/O chỉ còn một luồng
- Kết quả chứng minh rằng chỉ với tệp cấu hình Postgres cũng có thể gây suy giảm hiệu năng ở mức cực đoan
Tổng quan
Bài viết này trình bày một thí nghiệm đi ngược với hướng tinh chỉnh Postgres thông thường vốn tập trung vào việc làm cho hệ thống nhanh hơn, mà thay vào đó chỉ nhắm đến việc làm nó chậm đi, bằng cách thay đổi nhiều giá trị cấu hình của PostgreSQL để kéo hiệu năng xuống tới giới hạn.
Bài kiểm thử dựa trên workload TPC-C của BenchBase (128 kho, 100 kết nối, mỗi kết nối cố gắng đạt tối đa 10.000 giao dịch/giây, Postgres 19devel mới nhất, Ryzen 7950x, RAM 32GB, SSD 2TB, chạy trong 120 giây).
Ở giá trị mặc định, hiệu năng là 7082 TPS, và tác giả quan sát theo từng bước xem mỗi lần thao tác tham số làm hệ thống chậm đi đến mức nào.
Cắt giảm mạnh bộ đệm
- Postgres sử dụng bộ đệm mạnh mẽ (
shared_buffers) để giảm disk I/O - Khi giảm
shared_bufferstừ giá trị mặc định (10GB) xuống 8MB, TPS giảm còn khoảng 1/7 (1052 TPS) - Quan sát thấy tỷ lệ cache hit giảm từ 99,90% xuống 70,52%, còn số lần gọi
readsyscall tăng hơn 300 lần - Đã thử giảm xuống 128kB, nhưng Postgres chỉ cho phép tối thiểu khoảng 2MB, và TPS tiếp tục giảm xuống 485
Tăng công việc nền (autovacuum tuning)
- Đưa mọi ngưỡng liên quan đến
autovacuumxuống mức thấp nhất đểvacuumgần như chạy ở mỗi thao tác- Kết hợp như
autovacuum_vacuum_insert_threshold=1,autovacuum_naptime=1v.v. vacuumlặp lại gần như mỗi giây ngay cả khi thực tế không có nhiều việc để làm
- Kết hợp như
- Trong quá trình này, giảm
maintenance_work_memxuống 128kB và bật toàn bộ logging choautovacuum - Kết quả là TPS giảm xuống 293 (chưa tới 1/20 so với ban đầu)
- Log thời gian thực liên quan đến
autovacuumxác nhận rằng công việc nền diễn ra thường xuyên là nguyên nhân làm giảm hiệu năng
Làm tệ nhất việc ghi WAL (Write-Ahead Log)
- Điều chỉnh toàn bộ tham số liên quan đến WAL sang trạng thái tệ nhất
wal_writer_flush_after=0,wal_writer_delay=1,wal_sync_method=open_datasyncv.v.- Ép
checkpointmỗi 30 giây, giữmin/max_wal_size=32MBở mức tối thiểu wal_level=logical,wal_log_hints=onđể ghi cả những thông tin không cần thiết vào WAL- Bật thêm tải như
track_wal_io_timing,summarize_wal
- Kết quả TPS giảm xuống 98 (chưa tới 1/70 so với ban đầu)
- Log cho thấy các
checkpointlặp lại chỉ sau vài trăm ms, xác nhận hành vi bất thường
Loại bỏ hiệu quả của chỉ mục
- Đặt các giá trị khiến chi phí sử dụng chỉ mục đều bị tính ở mức tối đa (
random_page_cost=1e300,cpu_index_tuple_cost=1e300), về thực chất là vô hiệu hóa chỉ mục - Tăng
shared_bufferstrở lại 8MB (để đảm bảo ổn định), TPS giảm xuống 0,87 (đạt mức chậm hơn 7.000 lần)
Ép I/O về một luồng duy nhất
- Tận dụng tính năng mới của Postgres 18+
- Đặt
io_method=worker,io_workers=1để ép mọi I/O chạy qua một worker thread duy nhất - TPS tiếp tục giảm xuống 0,016 (chậm hơn 42.000 lần)
- Với 100 kết nối và thời gian thử nghiệm 120 giây, chỉ có 11 giao dịch thành công, cho thấy hiệu năng bị bóp nghẹt nghiêm trọng
Kết luận và hướng dẫn tái hiện
- Chứng minh rằng chỉ với tổng cộng 32 thao tác chỉnh tham số cũng có thể đẩy DB vận hành vào trạng thái gần như "tê liệt"
- Có thể tối đa hóa mức suy giảm hiệu năng chỉ bằng cách can thiệp vào cấu hình
postgresql.conf - Người muốn tái hiện thí nghiệm có thể tham khảo BenchBase Postgres, môi trường TPC-C đã nêu ở trên và toàn bộ danh sách thiết lập
- Một số tham số phụ hoặc các thử nghiệm làm chậm thêm không được đưa vào
Danh sách tham số tóm tắt
shared_buffers = 8MB- Các
thresholds/scale_factorliên quan đếnautovacuum= hạ xuống mức thấp nhất 0~1 - Chi phí, bộ nhớ và log liên quan đến
vacuum: hạ thấp/tăng tối đa - Đồng bộ/flush/log/level liên quan đến WAL: giữ ở trạng thái chậm
random_page_cost,cpu_index_tuple_costliên quan đến chỉ mục: đặt thành1e300io_method = worker,io_workers = 1- Các giá trị chi tiết khác xem danh sách trong bài
Kết bài
- Chỉ riêng tệp
postgresql.confcũng có thể gây ra suy giảm hiệu năng cực lớn - Trong thực tế, có thể tham khảo ngược tổ hợp này để cải thiện hiệu năng một cách hiệu quả
- Bài viết khép lại với việc tác giả nhắc đến chuyện phải dừng thử nghiệm vì đau lưng
2 bình luận
Ý kiến Hacker News
Tuyệt vời. Tôi rất thích cách tiếp cận này.