Xử lý large dataset trong MySQL (hàng chục triệu → trăm triệu record) cần chia theo nhiều lớp: thiết kế schema → index → query → partition → hạ tầng.
Dưới đây là checklist thực chiến 👇
INT thay vì BIGINT nếu không cầnVARCHAR(100) thay vì TEXTVí dụ:
user_id INT UNSIGNED NOT NULL
Ví dụ:
CREATE INDEX idx_user_created ON orders(user_id, created_at);
Sai:
SELECT * FROM orders LIMIT 1000000, 20;
→ MySQL phải scan 1 triệu dòng
SELECT * FROM orders WHERE id > 1000000 LIMIT 20;
Nhanh hơn rất nhiều.
Chia bảng theo:
Ví dụ partition theo tháng:
PARTITION BY RANGE (YEAR(created_at)) (
PARTITION p2024 VALUES LESS THAN (2025),
PARTITION p2025 VALUES LESS THAN (2026)
);
👉 Giúp MySQL chỉ scan partition cần thiết.
Ví dụ:
Hoặc:
Sai:
SELECT * FROM big_table;
Đúng:
SELECT * FROM big_table WHERE id BETWEEN 1 AND 10000;
Xử lý theo batch 10k record.
PHP:
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false
Tránh OOM.
1 server:
Scale đọc rất tốt.
Trong my.cnf:
innodb_buffer_pool_size = 70% RAM innodb_log_file_size = 1G max_connections = 200
Kiểm tra:
SHOW ENGINE INNODB STATUS;
Ví dụ:
Giảm size bảng active.
Khi cần search full text hoặc analytics lớn:
Dùng:
slow query logEXPLAINSHOW PROCESSLISTHoặc tool nhẹ:
| Size | Cách xử lý |
|---|---|
| < 1M | Index đúng là đủ |
| 1M–10M | Keyset pagination |
| 10M–100M | Partition + Replica |
| > 100M | Sharding / DB chuyên biệt |