Bài trước log_min_duration_statement bắt được câu chậm và ghi nguyên văn nó vào log. Nhưng nguyên văn thôi chưa đủ — bạn cần kế hoạch của đúng lần chạy chậm đó để biết vì sao. Vấn đề: khi bạn chạy lại EXPLAIN ANALYZE, dữ liệu đã khác, cache đã nóng, và bạn không tái hiện được cơn chậm. Giải pháp là auto_explain — nó tự đính kèm kế hoạch đầy đủ vào log ngay lúc câu chậm xảy ra.
Tự chụp kế hoạch, ngay khi chậm
auto_explain là một contrib module: khi một truy vấn vượt ngưỡng thời gian, nó tự ghi EXPLAIN (thậm chí EXPLAIN ANALYZE) của câu đó vào log. Bạn không phải có mặt, không phải chạy lại gì cả.

Hình 1: Bật auto_explain (thêm vào preload, khởi động lại), rồi cấu hình. log_min_duration là ngưỡng (chỉ chụp câu vượt). log_analyze = on biến nó thành EXPLAIN ANALYZE — cho số thực, không chỉ ước lượng. log_buffers = on thêm số trang cache/đĩa. log_nested_statements = on bắt cả câu chạy bên trong hàm/thủ tục.
Log thật: cả kế hoạch ANALYZE, không cần chạy lại
Đặt ngưỡng 50 ms với log_analyze, chạy một câu chậm, rồi đọc log:

Hình 2: Thật. Log ghi duration: 78.046 ms plan: rồi toàn bộ cây kế hoạch với actual time, rows, và Buffers — đúng như EXPLAIN (ANALYZE, BUFFERS) mà ta học ở các bài đầu. Nhìn là thấy ngay thủ phạm: Parallel Seq Scan quét cả bảng, vứt bỏ 1.651.573 dòng không khớp, đọc 82.932 trang từ đĩa. Tất cả được ghi lại tự động, lúc câu chậm xảy ra — không cần bạn có mặt hay chạy lại.
Vì sao đây là mảnh ghép quan trọng
Ba công cụ giám sát ta đã học ghép thành một quy trình hoàn chỉnh:
pg_stat_statements(bài 7): truy vấn nào tốn tổng nhiều nhất — nhìn bức tranh lớn.log_min_duration_statement(bài 8): lần chạy nào chậm, kèm tham số thật.auto_explain(bài này): vì sao lần đó chậm — kế hoạch thực tế của chính nó.
Đặc biệt với những cơn chậm không tái hiện được (dữ liệu lệch theo thời điểm, cache lạnh, một tham số hiếm), auto_explain là cách duy nhất bắt được kế hoạch thật. Không có nó, bạn chỉ biết "câu này thỉnh thoảng chậm" mà không bao giờ thấy được kế hoạch lúc nó chậm.
Cái giá phải cân nhắc
log_analyze = on không miễn phí — nó bật đo lường (instrumentation) ở mức như EXPLAIN ANALYZE, và chi phí này áp lên mọi truy vấn chạy qua (dù chỉ câu vượt ngưỡng mới được ghi). Trên hệ thống tải rất cao, chi phí đo có thể đáng kể. Cách dùng an toàn:
- Đặt
log_min_durationđủ cao (vài trăm ms) để chỉ quan tâm câu thật chậm. - Bật
log_analyzecó chọn lọc — chỉ khi đang truy một vấn đề, hoặc chỉ trên một user/session, rồi tắt. auto_explain.sample_rate(< 1.0) để chỉ chụp một phần các câu, giảm tải khi cần theo dõi liên tục.- Nếu chỉ cần kế hoạch ước lượng (không đo thật), để
log_analyze = off— nhẹ hơn nhiều, vẫn thấy cấu trúc kế hoạch.
Ba ý mang về
auto_explaintự ghi kế hoạch của truy vấn chậm vào log — đã thấy thật: một câu 78 ms được log kèmEXPLAIN (ANALYZE, BUFFERS)đầy đủ (actual time,rows,Buffers,Rows Removed by Filter), không cần chạy lại.- Nó là mảnh ghép cuối của bộ ba giám sát:
pg_stat_statements(tổng thể) +log_min_duration_statement(lần chậm) +auto_explain(vì sao) — đặc biệt vô giá với cơn chậm không tái hiện được. log_analyze=oncó chi phí đo trên mọi câu — đặtlog_min_durationcao, bật chọn lọc, dùngsample_rateđể kiểm soát; hoặc đểlog_analyze=offnếu chỉ cần kế hoạch ước lượng.
Ta đã trọn bộ công cụ đo lường: EXPLAIN, BUFFERS, cost, và ba tầng giám sát. Còn một cách nữa để đọc kế hoạch dễ hơn với truy vấn phức tạp. Phần sau dùng EXPLAIN (FORMAT JSON) và các công cụ trực quan để biến cây kế hoạch chằng chịt thành sơ đồ dễ nhìn — khép lại mô-đun nền tảng đo lường trước khi ta bước vào thế giới index.