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

101 truy vấn, câu nào cũng dưới 0,2ms — vì sao đo cục bộ giấu mất thảm họa N+1 qua mạng

Lấy 100 bài rồi mỗi bài một truy vấn bình luận: 101 truy vấn, mỗi câu <0,2ms, đo cục bộ chỉ chậm 3 lần một JOIN nên tôi suýt xem thường. Nhưng qua mạng, 100 round-trip tuần tự làm N+1 chậm 10-100 lần. Số round-trip mới là đại lượng quyết định, và pg_stat_statements với calls=100 là dấu vết để nhận ra.

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

Trang 1 nhanh 0,02ms, trang cuối treo 64ms: vì sao OFFSET giết phân trang ở trang sâu

Phân trang OFFSET 0 quét 20 hàng (0,02ms), nhưng OFFSET 500000 quét 500020 hàng (34ms) và trang cuối quét cả triệu hàng (64ms). Chi phí tăng tuyến tính theo độ sâu — và tôi suýt bỏ qua vì chỉ thử trang đầu. Keyset pagination nhảy thẳng qua index, nhanh đều 0,03ms mọi trang. Vì sao OFFSET đếm còn keyset tra cứu.

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

int hay bigint hay text — đo ra cùng 35 MB, và vì sao kết luận đó gần như sai hoàn toàn

Đo dung lượng bằng bảng một cột: int, bigint, numeric, text đều ra 35 MB y hệt — tôi suýt kết luận kiểu chẳng ảnh hưởng. Header hàng 23 byte đã trùm mất khác biệt. Cho cột thành phần lớn của hàng thì bigint 89MB so int 57MB, numeric chậm 2,7 lần, và text so số sai ('10' < '9'). Chọn kiểu là chuyện dung lượng, tốc độ, và tính đúng.

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

WHERE diem <> 7 nuốt mất 200.000 hàng: cái bẫy NULL mà mọi lập trình viên SQL đều vấp

Viết WHERE diem <> 7 để lấy mọi hàng không phải 7, đợi 990000, đo ra 790000 — 200000 hàng NULL biến mất lặng lẽ. NULL không phải giá trị, so sánh với nó ra 'unknown' và WHERE loại sạch. NOT IN với một NULL trả 0 hàng, AVG bỏ NULL, và hàng toàn NULL còn nhỏ hơn trên đĩa. Logic ba trạng thái của SQL, đo tận nơi.

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

Kiểm email trùng ở tầng app là đủ? Hai request song song lọt cả hai, và chỉ CSDL chặn được

Tưởng kiểm trùng email ở tầng ứng dụng là đủ — cho hai request chạy song song thì cả hai lọt, hai dòng trùng vào bảng. Chỉ UNIQUE ở CSDL mới chặn thật dưới đồng thời. Đo: vi phạm ràng buộc bị từ chối ngay với lỗi rõ, và khóa ngoại không đánh index bên con khiến xóa cha chậm 80 lần.

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

SELECT 1 chỉ 0,028ms, sao app chỉ chạy 1499 truy vấn/giây? Chi phí ẩn của mỗi kết nối

Đo truy vấn nhẹ ra 0,028ms rồi nhẩm 'app gọi vài chục nghìn lần một giây thoải mái'. Nhưng đó là khi tái dùng kết nối — mở kết nối mới mỗi lần chỉ còn 1499 tps, chậm 23 lần. Mỗi kết nối PostgreSQL là một tiến trình phải fork; chi phí mở đường lấn át chính truy vấn. Vì sao pool kết nối là lời giải, không phải tăng max_connections.