VNEngineerDBMySQLKhi query dữ liệu non-image (SELECT * mà có cột blob) lại rất nặng?
Khi query dữ liệu non-image (SELECT * mà có cột blob) lại rất nặng?
Lý do SELECT * có cột BLOB khiến query rất nặng nằm ở 3 tầng khác nhau:
⚙️ 1. Cơ chế lưu trữ và nạp dữ liệu của MySQL
MySQL không biết bạn “chỉ cần metadata, không cần ảnh”, nên khi bạn SELECT *, nó đọc toàn bộ nội dung của cột BLOB từ disk vào RAM, rồi mới gửi sang client. Dù bạn không dùng tới trường đó, quá trình vẫn xảy ra.
Nếu ảnh là vài trăm KB hoặc vài MB → mỗi dòng query sẽ phải load từng ấy dữ liệu.
1.000 dòng × 500KB = 500MB phải truyền qua network MySQL → PHP → webserver.
➡️ Kết quả: query tốn thời gian, RAM và băng thông cực lớn.
🧩 2. Cách MySQL quản lý bộ nhớ tạm (buffer)
Khi MySQL Server xử lý query có BLOB:
Nó phải dựng buffer động để chứa cột lớn này trong bộ nhớ.
Buffer lớn → tăng memory usage → dễ đụng max_allowed_packet hoặc sort_buffer_size.
Nếu server bị ép bộ nhớ, MySQL có thể swap ra disk, khiến query chậm cực kỳ.
🌐 3. Truyền dữ liệu qua network đến client (PHP)
Sau khi MySQL load xong:
Dữ liệu BLOB được chuyển nguyên dạng binary qua socket tới PHP.
PHP MySQLi/PDO lại phải nhận toàn bộ chuỗi byte, giải mã, lưu vào memory của tiến trình PHP.
Nếu bạn query nhiều dòng, bộ nhớ PHP sẽ phình rất nhanh → Allowed memory size exhausted.
💡 Kết luận
Tình huống
Tác động
SELECT * FROM media_files (có cột BLOB)
Nặng, đọc toàn bộ dữ liệu ảnh
SELECT id, file_name FROM media_files
Nhẹ, chỉ đọc metadata
SELECT file_data FROM media_files WHERE id = ?
Hợp lý, chỉ lấy khi thực sự cần ảnh
✅ Cách khắc phục
Không bao giờ dùng SELECT * trên bảng có BLOB. → Luôn chỉ định cột cụ thể.
Nếu bạn hay cần metadata + ảnh → tách ảnh sang bảng riêng: media_meta(id, name, mime_type, size) media_data(id, file_data LONGBLOB)
Giảm kích thước ảnh, nén base64 hoặc WebP trước khi insert.
Hưng Đặng
Some tourists think Amsterdam is a city of sin, but in truth it is a city of freedom. And in freedom, most people find sin. The Fault In Our Stars.