EXPLAIN cho xem kế hoạch mà bộ tối ưu định chạy (không thực thi). EXPLAIN ANALYZE chạy thật rồi so sánh số dòng ước lượng với số dòng thực — đây là công cụ chẩn đoán hiệu năng số một (cẩn thận với DML trên production vì nó thực sự ghi). Thêm BUFFERS để thấy đọc từ cache hay disk.
Cách đọc: từ trong ra ngoài, dưới lên trên (node trong cùng chạy trước). cost=(startup..total) chỉ là ước lượng tương đối, không phải mili-giây; actual time mới là thời gian thật.
Vài node hay gặp:
- Seq Scan: quét cả bảng — ổn khi lấy phần lớn dòng hoặc bảng nhỏ.
- Index Scan / Index Only Scan: tra qua index; "Only" nghĩa là không cần đụng bảng (covering index, rất nhanh).
- Hash Join / Nested Loop / Merge Join: ba cách ghép bảng tùy kích thước và có index hay không.
Dấu hiệu cần lưu ý:
- Ước lượng vs thực tế lệch nhiều → thống kê cũ, chạy ANALYZE table.
- Seq Scan trên bảng lớn trong điều kiện WHERE → thiếu index.
- Buffers đọc từ disk cao → dữ liệu không nằm trong cache.
EXPLAIN shows the plan the optimizer intends to run (without executing). EXPLAIN ANALYZE actually runs it and compares estimated vs actual rows — it's the number-one performance diagnostic tool (be careful with DML on production since it really writes). Add BUFFERS to see cache vs disk reads.
How to read it: inside-out, bottom-to-top (the innermost node runs first). cost=(startup..total) is only a relative estimate, not milliseconds; actual time is the real timing.
A few common nodes:
- Seq Scan: scans the whole table — fine for fetching most rows or for small tables.
- Index Scan / Index Only Scan: looks up via index; "Only" means it never touches the table (covering index, very fast).
- Hash Join / Nested Loop / Merge Join: three ways to join tables depending on size and whether an index exists.
Red flags:
- Big gap between estimated and actual rows → stale statistics, run ANALYZE table.
- Seq Scan on a large table in a WHERE condition → missing index.
- High disk Buffers reads → the data isn't in cache.