Lý do SELECT * có cột BLOB khiến query rất nặng nằm ở 3 tầng khác nhau:
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.
➡️ Kết quả: query tốn thời gian, RAM và băng thông cực lớn.
Khi MySQL Server xử lý query có BLOB:
max_allowed_packet hoặc sort_buffer_size.Sau khi MySQL load xong:
Allowed memory size exhausted.| 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 |
SELECT * trên bảng có BLOB.media_meta(id, name, mime_type, size) media_data(id, file_data LONGBLOB)Việc query SELECT * có cột BLOB (Binary Large Object) trở nên nặng n bởi vì dữ liệu BLOB, dù không phải hình ảnh, vẫn là dữ liệu nhị phân lớn (file, tài liệu, video...) chiếm nhiều không gian và yêu cầu nhiều băng thông/bộ nhớ khi truyền tải, gây quá tải cho mạng, database và ứng dụng, làm chậm toàn bộ hệ thống do phải đọc và xử lý lượng dữ liệu khổng lồ này thay vì chỉ lấy metadata.
Nguyên nhân chính:
SELECT * vẫn cố gắng lấy toàn bộ nội dung file đó, rất tốn tài nguyên.Giải pháp:
SELECT *: Chỉ chọn các cột cần thiết. Nếu cần BLOB, chỉ lấy cột đó khi thực sự cần dùng (ví dụ: khi người dùng click vào tải file).TOP N hoặc phân trang (Pagination): Lấy từng phần nhỏ dữ liệu hoặc giới hạn số lượng record trả về ban đầu.OFFSET FETCH hoặc ROW_NUMBER(): Phân trang dữ liệu hiệu quả hơn.Ví dụ thay đổi Query (SQL):
Thay vì: SELECT * FROM Documents;
Hãy dùng: SELECT DocID, DocName, DocType FROM Documents; (Chỉ lấy metadata)
Khi cần file:SELECT DocContent FROM Documents WHERE DocID = 123; (Chỉ lấy cột BLOB khi cần)