Q

Quản trị viên

Là một lập trình viên yêu công nghệ, thích viết blog để chia sẻ kiến thức, kinh nghiệm lập trình và những điều thú vị trong thế giới tech.

2300 bài viết · Website
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

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.

Hệ điều hành 03/09/2026 9 phút

Working-set nhích từ 80MB lên 150MB, tốc độ rơi 1.500 lần: cái vực thrashing ẩn ngay sau ngưỡng RAM

Working-set 80MB trong 100MB RAM: 0 major fault, 900.000 MB/s. Đẩy lên 150MB (tràn 54MB ra swap): 9.000 major fault mỗi lần quét, còn 600 MB/s — chậm 1.500 lần. Swap không phải 'thêm RAM' mà là vùng tràn chậm gấp nghìn lần, và cái vực đó vô hình cho tới đúng ngưỡng working-set gặp RAM.

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

Bảng 81MB nhỏ hơn cache 128MB mà chạy 3 lần vẫn không nóng lên — bí mật của ring buffer

Lần đọc đầu là shared read (nạp trang), lần sau thành shared hit (từ RAM). Nhưng một seq scan bảng lớn KHÔNG vào cache dù bảng nhỏ hơn shared_buffers — vì ring buffer cố ý bảo vệ cache khỏi bị một lần quét lớn xóa sạch. Tôi tưởng 'chạy lại luôn nhanh hơn', hóa ra đó không phải luật tự nhiên.