Họ đang đo gì
Bạn có biết phân mảnh là phương án CUỐI không, và có nghĩ tới truy vấn xuyên mảnh không.
Trả lời ngắn~30 giây
Chỉ phân mảnh khi lưu lượng GHI vượt quá khả năng của một node, sau khi đã thử replica cho đọc, index tốt hơn, cache, và tách bảng nóng ra instance riêng. Khoá phân mảnh nên là thứ mà hầu hết truy vấn đều có sẵn trong điều kiện lọc — thường là tenant_id hoặc user_id — vì truy vấn không có khoá phải hỏi TẤT CẢ các mảnh rồi gộp, và đó là thứ giết chết hiệu năng chứ không phải bản thân việc phân mảnh.
Giải thích sâu
Ba cách phân mảnh có ba hồ sơ vận hành khác nhau. Theo khoảng (range) dễ hiểu và cho phép quét theo dải, nhưng tạo điểm nóng — phân theo ngày thì mảnh của hôm nay nhận toàn bộ lưu lượng ghi. Theo hash thì phân bố đều, đổi lại mất khả năng quét dải và thêm mảnh là phải phân phối lại gần hết dữ liệu. Consistent hashing giảm phần phải di chuyển xuống còn khoảng 1/n, nên đó là lựa chọn mặc định khi bạn biết mình sẽ còn thêm mảnh.
Điều đau nhất trong thực tế không phải chọn cách phân mảnh mà là những thứ bạn mất: khoá ngoại xuyên mảnh không tồn tại, transaction xuyên mảnh cần điều phối, JOIN giữa hai mảnh phải làm ở tầng ứng dụng, và AUTO_INCREMENT không dùng được nên bạn cần UUID hoặc Snowflake id. Mỗi thứ này là một lớp phức tạp thêm vào MỌI tính năng bạn viết sau đó, không phải chỉ một lần khi thiết lập.
Về việc chọn khoá, câu hỏi kiểm tra tốt nhất là: liệt kê mười truy vấn quan trọng nhất và đếm xem bao nhiêu cái có khoá phân mảnh trong điều kiện. Dưới tám trên mười thì khoá sai. Với hệ thống nhiều tenant thì tenant_id gần như luôn đúng, trừ khi có một tenant khổng lồ chiếm phần lớn dữ liệu — lúc đó bạn cần khoá ghép hoặc tách riêng tenant đó ra, và nói được điều này cho thấy bạn đã gặp bài toán thật.
Câu hỏi tiếp theo họ sẽ hỏi
?Phân mảnh lại khi đang chạy thì làm sao?
Ghi kép trong một giai đoạn: ghi vào cả bố cục cũ và mới, sao chép nền phần dữ liệu cũ, đối chiếu, rồi chuyển đọc sang bố cục mới, cuối cùng mới ngừng ghi vào cũ. Nhiều tuần chứ không phải một đêm, và phải có đường lùi ở mọi bước.
Trả lời thế này là mất điểm
- Phân mảnh vì “sau này sẽ lớn”. Bạn trả toàn bộ chi phí phức tạp ngay hôm nay cho một quy mô có thể không bao giờ tới.
- Chọn khoá phân mảnh mà chưa liệt kê các truy vấn chính. Đó là quyết định không thể sửa rẻ.
Nguồn
- Martin Kleppmann, Designing Data-Intensive Applications, ch. 6 — Partitioning
- Vitess — Sharding (kiến trúc phân mảnh cho MySQL ở quy mô lớn)