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

VACUUM dọn 20000 xác về 0 mà bảng vẫn 712kB — tôi tưởng nó không chạy, hóa ra tôi đo nhầm chỉ số

VACUUM dọn 20000 dead tuple về 0 nhưng bảng vẫn đúng 712kB — nó đánh dấu chỗ trống để tái dùng chứ không trả đĩa. Tôi tưởng VACUUM hỏng vì nhìn kích thước file, hóa ra phải nhìn n_dead_tup. VACUUM FULL mới nén còn 8kB nhưng khóa bảng — hai lệnh gần tên mà khác hẳn tác động.

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

Có index trên đúng cột mà vẫn quét cả bảng 141ms — vì bạn tạo nhầm LOẠI index

Tìm tài liệu chứa một từ trên 200k dòng: không index 141ms, một B-tree cũng 141ms (bị bỏ qua hoàn toàn), nhưng GIN chỉ 0,28ms — nhanh 500 lần. B-tree không hiểu toán tử 'chứa từ'. Loại index phải khớp phép toán truy vấn, không chỉ khớp cột — và EXPLAIN là trọng tài.

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

Truy vấn quét 2 triệu hàng để tìm 40 — một index kéo nó nhanh 113 lần

Bài kết sê-ri Cơ sở dữ liệu: quy trình tối ưu đúng là đo trước, đọc kế hoạch thật, sửa một thứ, đo lại. Một vòng trọn vẹn: WHERE khach=X quét cả 2 triệu hàng (17 ms) chỉ để tìm 40; EXPLAIN chỉ thẳng, thêm index, đo lại 0,15 ms — nhanh 113 lần. Không đoán, không cãi — đo là xong.

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

Tìm một email trong 1 triệu hàng: không index mất 14ms, có index 0,03ms — nhanh 400 lần

Tìm một email trong bảng 1 triệu hàng: không index quét 7353 trang mất 14ms; có index đọc 4 trang mất 0,034ms — nhanh 400 lần, đọc ít 1800 lần. Nhưng tôi suýt khoe 'nhanh 1600 lần' vì đọc nhầm 'cost' như thời gian. Cost là ước lượng của planner, actual time mới là đồng hồ. Bài mở đầu sê-ri Cơ sở dữ liệu.