2014-11-07 14 views
5

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; 

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

  1. Các EXPLAIN QUERY PLAN trong cả hai trường hợp là

    0 | 0 | 0 | SCAN TABLE file đính kèm

  2. Sự phủ IS NOT NULL vs length() != 0 kết quả trong việc thực hiện tương tự chênh lệch 250ms so với 2ms.

  3. 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.
+0

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? –

+0

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"? –

+1

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". –

Trả lời

4

Đây là những câu hỏi đơn giản khác nhau: LENGTH là một hàm vô hướng trả về (xem here)

(i) NULL nếu đầu vào là NULL
(ii) 0 nếu đầu vào là một chuỗi của zero chiều dài (hoặc nếu nó được chuyển đổi thành một chuỗi, resp.).

Do đó, điều kiện length(content)=0 là đúng đối với nội dung là chuỗi rỗng và sai khi nội dung là NULL (vì so sánh với NULL luôn là sai).

Dựa trên điều này, tôi đoán rằng bảng của bạn có chứa một số trường NULL và chỉ một số có chứa giá trị. Điều này cũng được hỗ trợ bởi thông tin bổ sung thứ hai của bạn, nơi bạn nói rằng IS NOT NULL cho thấy một hiệu suất tương đương.

+0

Tôi muốn trỏ cùng một điều IS NULL <> len (nội dung) = 0. Nếu trường là '' len (nội dung) = 0 nhưng nếu trường là null len (nội dung) = null – CiucaS

+0

Điểm tốt, 'chiều dài (NULL)! = 0' –

+0

Dựa trên câu trả lời của bạn, tôi thấy rằng kết quả 'dài (nội dung) IS NULL' trong cùng hàng với' nội dung IS NULL' vì 'length (X) = NULL' nếu và chỉ nếu' X = NULL ', nhưng thậm chí còn nhanh hơn (500x trong trường hợp của tôi và 20x đối với trường hợp không phải dạng trống). Nếu bạn có thể xác minh và thêm điều đó vào câu trả lời, tôi rất muốn chấp nhận nó. –

Các vấn đề liên quan