Bài viết mới nhất

Tổng 2300 bài
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.

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

Window function: tính theo nhóm mà vẫn giữ từng dòng — và nhanh hơn self-join 124 lần

GROUP BY gộp nhóm lại làm mất chi tiết từng dòng. Window function tính toán theo nhóm (xếp hạng, tổng luỹ kế, so kỳ trước) mà VẪN giữ mọi dòng — thứ mà nhiều người viết bằng self-join phức tạp và chậm. Bài này đo thật trong PostgreSQL: ROW_NUMBER/RANK/DENSE_RANK khác nhau khi có tie, running total + LAG, và một benchmark đắt giá — window làm running total trên 30.000 dòng mất 15.9ms, còn self-join tương quan chỉ 3.000 dòng đã mất 1971ms.

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

CTE và recursive CTE: viết query dễ đọc, duyệt cây — và bẫy MATERIALIZED chậm 1000 lần

CTE (WITH) chia query rối rắm thành các bước có tên, dễ đọc; recursive CTE duyệt cây/đồ thị chỉ bằng một câu SQL. Nhưng có một bẫy hiệu năng: bài này đo thật trong PostgreSQL — cùng một query lấy WHERE id=500000 trên bảng 1 triệu dòng, CTE thường (inline) dùng Index Scan chỉ 0.098ms, còn thêm MATERIALIZED buộc quét cả 1 triệu dòng mất 99.756ms — chậm hơn 1000 lần. Kèm recursive CTE dựng cây tổ chức từ CEO xuống.

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

Tiny allocator của Go: gộp object nhỏ để một byte chỉ tốn một byte

Object tí hon rất phổ biến nhưng cấp mỗi cái một slot 8-16 byte quá phí. Tiny allocator gộp object dưới 16 byte không con trỏ vào chung khối 16B. Đo thật: object 1-byte nén xuống đúng 1.0 B mỗi cái (thắng 8 lần), nhưng cùng cỡ mà có con trỏ thì không được gộp. Go 1.23.

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

Phân trang: vì sao OFFSET 1 triệu chậm 3000 lần, và keyset pagination giữ tốc độ phẳng

OFFSET LIMIT là cách phân trang ai cũng viết, và nó hoạt động hoàn hảo... cho tới trang thứ 50.000. Bài này đo thật trên bảng 2 triệu dòng: OFFSET chậm dần tuyến tính — trang đầu 0.029ms nhưng trang cuối 144.941ms, vì nó phải đọc qua 1.000.020 dòng chỉ để lấy 20. Keyset pagination (WHERE id > last_id) giữ ~0.04ms phẳng ở mọi trang. Kèm plan chứng minh OFFSET quét rồi vứt, keyset nhảy thẳng.

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

Statistics và planner: vì sao query 'đột nhiên chậm' — khi database đoán sai số dòng

Planner PostgreSQL không biết dữ liệu của bạn — nó ƯỚC LƯỢNG từ thống kê rồi chọn plan. Thống kê sai thì chọn plan tệ. Bài này đo thật: một bảng chèn 500.000 dòng nhưng chưa ANALYZE khiến planner ước lượng 1 dòng trong khi thực tế 5000 (chọn plan chậm 15.5ms); ANALYZE đưa về đúng, plan nhanh gấp đôi. Và cột tương quan (city suy ra country) khiến planner ước lượng thấp 4 lần — CREATE STATISTICS sửa từ ~23.000 về 99.500 sát thực tế 100.000.