Index-only scan là khi database lấy được toàn bộ dữ liệu cần ngay trong index, khỏi phải mở thêm bảng (heap) — nên đỡ I/O và nhanh hơn. Điều kiện: index chứa đủ mọi cột query cần, và "visibility map" xác nhận vùng dữ liệu đó đã ổn định để khỏi kiểm tra lại bảng.
Có thể giúp planner bằng covering index — thêm cột cần đọc vào INCLUDE:
sql
CREATE INDEX idx_orders_user_created
ON orders (user_id, created_at DESC) INCLUDE (total, status);Nhưng nếu bảng vừa bị update nhiều, visibility map chưa kịp "sạch", PostgreSQL vẫn phải đọc bảng — lúc đó index-only scan mất tác dụng.
Đây là lý do nó không phải lúc nào cũng xảy ra.