Tôi đang có một cơ sở dữ liệu ~ 90 MB bao gồm chủ yếu là tệp đính kèm thư bao gồm cột BLOB content
, lưu trữ dữ liệu tệp đính kèm nhị phân.Tại sao 'IS NULL' 100x chậm hơn 'length() = 0' trên một cột blob?
Tôi cho rằng không phải là khôn ngoan khi tạo chỉ mục qua BLOB, vì vậy không có chỉ mục nào liên quan ngoài việc tự động hóa.
Để nhận được file đính kèm rỗng, tôi đã so sánh querys sau:
SELECT message_id FROM attachments WHERE content IS NULL;
và
SELECT message_id FROM attachments WHERE length(content) = 0;
đó dẫn đến việc hàng cùng trong usecase của tôi.
Tại sao người đầu tiên mất 250ms và người thứ hai chỉ có 1-2ms (cả trên SSD)? Lý do đằng sau điều đó là gì? Có chỉ số chiều dài ẩn hay gì đó không? Bất kỳ sự hiểu biết nào được đánh giá cao
thông tin bổ sung
Các
EXPLAIN QUERY PLAN
trong cả hai trường hợp là0 | 0 | 0 | SCAN TABLE file đính kèm
Sự phủ
IS NOT NULL
vslength() != 0
kết quả trong việc thực hiện tương tự chênh lệch 250ms so với 2ms.- Trong truy vấn kết hợp chỉ bao gồm các cột {NULL}
WHERE content IS NULL AND length(content) = 0;
mất 250ms vàWHERE length(content) = 0 AND content IS NULL;
mất 2ms.
Bạn có chắc chắn so sánh của mình là chính xác không? Dữ liệu chỉ được lưu trong bộ nhớ cache? Điều gì xảy ra nếu, sau khi khởi động một phiên bản mới của ứng dụng khách sqlite, trước tiên bạn thực hiện truy vấn thứ hai? Hoặc lặp lại từng truy vấn một vài lần, chạy nhanh nhất dưới dạng tham chiếu? –
Tôi có thể tạo nhanh thời gian truy vấn nhanh và không giới hạn theo bất kỳ thứ tự nào trong một hoặc nhiều quy trình sqlite3. Bạn có ý nghĩa gì với "so sánh là chính xác"? –
Tôi cho rằng điều này là do chiều dài cột được lưu trữ, do đó kiểm tra độ dài không yêu cầu nội dung của BLOB được truy xuất. Bạn vẫn phải quét từng bản ghi, nhưng có ít nhất một lần đọc bổ sung cho mỗi bản ghi cho kiểm tra NULL. Tất nhiên, IS NULL có thể/nên được tối ưu hóa để sử dụng độ dài bản ghi. Hãy xem https://www.sqlite.org/fileformat2.html, đặc biệt là phần "2.1 Định dạng bản ghi". –