Cơ sở dữ liệu 03/09/2026 8 phút

0,001ms trong EXPLAIN — nhưng nó chạy 1999 lần: cái bẫy loops của nested loop join

Nested loop join với bảng ngoài nhỏ + bảng trong có index chỉ 0,027ms; cùng 2000 hàng nhưng bỏ index thì 156ms — chậm 83 lần. Và tôi suýt tưởng join miễn phí vì đọc actual time 0,001ms mà quên nhân với loops=1999. Đọc EXPLAIN phải nhân thời gian node trong với số vòng lặp.

Cơ sở dữ liệu 03/09/2026 8 phút

Hash join 78ms hay 223ms cho cùng một câu? Con số 'Batches' trong EXPLAIN nói tất cả

Join hai bảng lớn: hash join 78ms (bảng băm vừa RAM, Batches=1), nhanh gần 3 lần nested loop. Nhưng work_mem nhỏ làm bảng băm tràn 16 batch ra đĩa và chậm hẳn. Tôi suýt kết luận 'hash join nhanh' vô điều kiện — cho tới khi hạ work_mem và thấy Batches nhảy lên 16. Đọc Batches, không chỉ thời gian tổng.

Cơ sở dữ liệu 03/09/2026 9 phút

Merge join: 77ms khi dữ liệu đã sắp, 160ms khi phải tự sắp — và vì sao đừng vội chê nó thua hash

Merge join trên khóa đã sắp: 77ms không cần sort; nhưng trên cột chưa sắp phải thêm Sort tràn đĩa, 160ms (hash chỉ 78ms). Tôi suýt kết luận 'merge dở hơn hash' — cho tới khi thấy mình đo nó ở đúng điều kiện bất lợi. Đổi lại nó giữ nguyên thứ tự: ORDER BY LIMIT nhanh 0,03ms so với 72ms của hash.

Cơ sở dữ liệu 03/09/2026 8 phút

ORDER BY ... LIMIT 10 không sắp cả triệu hàng như bạn tưởng — nó chỉ giữ 10, tốn 25kB

ORDER BY trên 1 triệu hàng: work_mem nhỏ thì external merge tràn đĩa 208ms, lớn thì quicksort RAM 162ms. Nhưng ORDER BY LIMIT 10 dùng top-N heapsort chỉ 25kB, 53ms — không sắp hết. Đừng đoán thuật toán từ câu SQL; EXPLAIN cho biết cơ sở dữ liệu thật sự sắp thế nào, và một index có thể bỏ luôn bước sắp.

Cơ sở dữ liệu 03/09/2026 8 phút

Cùng 2 triệu hàng, GROUP BY này tốn 24kB còn kia tràn 62MB ra đĩa — khác nhau ở đâu?

GROUP BY 100 nhóm trên 2 triệu hàng dùng HashAggregate chỉ 24kB; nhưng GROUP BY 2 triệu nhóm phân biệt làm nó tràn 62MB ra đĩa. Tôi suýt kết luận 'GROUP BY nhẹ RAM bất kể bảng lớn'. Bộ nhớ tính theo SỐ NHÓM phân biệt, không phải số hàng — và đó cũng là cái bẫy của COUNT(DISTINCT).

Cơ sở dữ liệu 03/09/2026 8 phút

Planner đoán WHERE v<10 khớp 333350 hàng, thực tế 10000 — không phải nó dở, nó đang bị bịt mắt

Bảng vừa nạp 1 triệu hàng chưa ANALYZE: planner ước lượng WHERE v<10 là 333350 hàng, thực tế 10000 — lệch 33 lần. Tôi suýt trách planner ngu. Chạy ANALYZE, ước lượng về 9872, khớp. Thống kê bảng là nguồn của mọi ước lượng, và một planner mù thống kê buộc phải đoán bằng hằng số mặc định.