Thiết kế cho access pattern trước, rồi chọn partitioning + đúng index/PK sao cho mỗi query chỉ chạm một lát dữ liệu nhỏ, có giới hạn — không bao giờ scan 10 tỷ dòng. Dưới 100ms trên 10 tỷ bản ghi không phải chuyện ổ đĩa nhanh hơn; đó là chuyện làm cho working set thật nhỏ.
Query ─▶ Router ──▶ Partition (by tenant/time) ──▶ Index/PK lookup ─▶ ~thousands of rows
│ (prune 99.9% of data) (B-tree / sort key)
└─▶ Cache (Redis) ─▶ hit? return in <5ms
miss ▼
Columnar store (ClickHouse) for aggregates / scans
Access pattern quyết định tất cả
Trước khi chọn công nghệ, hỏi: "Lấy 20 đơn hàng gần nhất của user X" là query point/range — bạn muốn partition key và sort key khớp chính xác nó. "Tính tổng doanh thu theo vùng tháng này" là scan phân tích — row store là công cụ sai. Mô hình hoá query trước là thứ phân biệt một thiết kế chạy được với một thiết kế trông hợp lý nhưng full-scan.
