Lập trình 22/09/2026 6 phút

Đọc EXPLAIN ANALYZE: query plan là ống nghe của bác sĩ database, và cách nghe cho đúng

Query chậm mà không biết vì sao? EXPLAIN ANALYZE cho biết database THỰC SỰ làm gì với query của bạn. Bài này đo thật trên bảng 1 triệu dòng trong PostgreSQL: cùng một query, chưa index chạy Seq Scan mất 10.764ms (quét cả bảng, đọc 7353 block); thêm index thành Bitmap Index Scan còn 0.116ms (14 block) — nhanh 93 lần. Kèm cách đọc từng con số: cost không phải ms, actual time mới thật, và rows dự đoán vs thật lộ khi planner đoán sai.

Lập trình 22/09/2026 6 phút

Index B-tree: vì sao tạo index rồi vẫn Seq Scan — bẫy non-sargable và cách viết query cho đúng

Bạn tạo index nhưng query vẫn chậm và EXPLAIN vẫn báo Seq Scan? Vì predicate không sargable — chỉ cần bọc cột trong một hàm là index nằm im vô dụng. Bài này đo thật trên bảng 1 triệu dòng: WHERE email=x dùng index (0.045ms), nhưng lower(email)=x quét cả bảng (54.857ms); age+1=31 chậm 12ms còn age=30 chỉ 1ms; và một bất ngờ — LIKE 'x%' với index thường vẫn Seq Scan, phải dùng text_pattern_ops.

Lập trình 22/09/2026 6 phút

Index tổ hợp: thứ tự cột quyết định query nào dùng được, và covering index xoá luôn việc đọc bảng

Một index nhiều cột không phải muốn dùng sao cũng được — quy tắc leftmost prefix quyết định query nào tận dụng được nó. Bài này đo thật trên bảng 2 triệu dòng: index (user_id, created_at) giúp query lọc user_id (0.037ms) nhưng bó tay với query chỉ lọc created_at (Seq Scan 54ms); đổi thứ tự cột cho cùng query nhanh 14 lần; và covering index INCLUDE(payload) cho Index Only Scan với Heap Fetches=0 — trả lời trọn query mà không chạm bảng.

Lập trình 22/09/2026 6 phút

Ba thuật toán JOIN của PostgreSQL: nested loop, hash, merge — và vì sao planner chọn cái nào

JOIN không phải một phép — PostgreSQL có ba thuật toán để nối bảng, mỗi cái hợp một tình huống, và planner ước lượng để chọn. Bài này đo thật trên customers 1000 dòng ⋈ orders 2 triệu dòng: lọc một khách hàng thì Nested Loop chỉ 2.962ms; nối toàn bộ thì Hash Join (planner chọn) 133ms nhanh nhất, ép Nested Loop 187ms, ép Merge Join 301ms vì phải sắp xếp cả hai bên. Hiểu ba thuật toán để đọc plan và biết khi nào planner chọn sai.

Lập trình 22/09/2026 6 phút

N+1 query: ORM giấu 101 lần đấm xuống DB sau một vòng lặp — và cách gộp về 1 query

Bạn viết một vòng lặp vô hại trong ORM, và nó lặng lẽ bắn 101 query xuống database. Đó là N+1 — cái bẫy hiệu năng phổ biến nhất của backend. Bài này đo thật trong PostgreSQL: lấy 100 tác giả rồi lặp lấy sách từng người. Trên cùng một connection, N+1 chậm 2.7 lần; nhưng khi mỗi query là một round-trip thật (như app gọi qua mạng), N+1 mất 1110ms so với 17ms của một JOIN — chậm 64 lần. Chi phí không ở database, mà ở 101 lần đi-về cộng dồn.

Lập trình 22/09/2026 6 phút

Isolation level: tái hiện thật non-repeatable read và write skew, và vì sao READ COMMITTED không đủ

Transaction chạy đồng thời sinh ra các hiện tượng bất thường mà một mình bạn khó hình dung. Bài này tái hiện THẬT trong PostgreSQL bằng hai session: ở READ COMMITTED, cùng một transaction đọc balance hai lần ra 1000 rồi 500 (non-repeatable read); REPEATABLE READ giữ snapshot ổn định nên đọc lại vẫn 1000; và write skew — hai bác sĩ cùng xin nghỉ trực khiến còn 0 người trực ở REPEATABLE READ, nhưng SERIALIZABLE bắt được và abort một transaction.