2011-12-21 29 views
14

Tôi có một DB với một số trườngSQLite: Nên LIKE 'searchstr%' sử dụng chỉ mục?

word_id — INTEGER PRIMARY_KEY 
word — TEXT 
... 

..và ~ 150k hàng.

Vì đây là từ điển, tôi đang tìm kiếm một từ có mặt nạ 'search_string%' bằng LIKE. Nó được sử dụng để làm việc tốt, lấy 15ms để tìm hàng phù hợp. Bảng có chỉ mục cho một trường 'word'. Gần đây tôi đã sửa đổi bảng (một số trường của bảng đó nằm ngoài phạm vi) và một cái gì đó đã xảy ra - nó lấy 400ms để thực thi truy vấn, vì vậy tôi hiểu rằng vì nó không sử dụng chỉ mục ngay bây giờ. Truy vấn đơn giản với = thay vì hiển thị kết quả 10ms. Có ai đó có ý tưởng gì đang xảy ra ở đây không?

+0

tôi nghĩ vậy, bạn có thể muốn xem b-tree vì b-tree có hiệu quả trong phạm vi truy vấn và so sánh. – Jasonw

+0

Hmm, không chỉ mục giả sử tạo b-tree? Ý anh là, tôi nên tự mình tạo một cây b? – nikans

+0

Phần trăm luôn ở cuối cụm từ tìm kiếm của bạn, không bao giờ bắt đầu? – mikel

Trả lời

25

Không thể sử dụng chỉ mục một cách an toàn trong trường hợp này. Một thực hiện ngây thơ sẽ chuyển đổi này:

... WHERE word LIKE 'search_string%'

vào

... WHERE word >= 'search_string' AND word < 'search_strinh'

bằng cách tăng các ký tự cuối cùng của chuỗi tìm kiếm. Các toán tử lớn hơn và ít hơn có thể sử dụng một chỉ mục, trong đó LIKE không thể.

Thật không may, điều đó sẽ không hoạt động trong trường hợp chung. Toán tử LIKE không phân biệt chữ hoa chữ thường, có nghĩa là 'a' LIKE 'A' là đúng. Việc chuyển đổi ở trên sẽ phá vỡ bất kỳ chuỗi tìm kiếm nào có chữ cái viết hoa.

Trong một số trường hợp, tuy nhiên, bạn biết rằng độ nhạy trường hợp không liên quan đến một cột cụ thể và việc chuyển đổi ở trên là an toàn. Trong trường hợp này, bạn có hai lựa chọn.

  1. Sử dụng trình tự đối chiếu NOCASE trên chỉ mục bao gồm trường cụ thể này.
  2. Thay đổi hành vi của các LIKE điều hành chương trình toàn bằng cách chạy PRAGMA case_sensitive_like = ON;

Một trong những hành vi này sẽ cho phép SQLite để minh bạch làm việc chuyển đổi trên cho bạn; bạn cứ tiếp tục sử dụng LIKE như mọi khi và SQLite sẽ viết lại truy vấn cơ bản để sử dụng chỉ mục.

Bạn có thể đọc thêm về "Tối ưu hóa thích" trên SQLite Query Optimizer Overview page.

+1

Chết tiệt! Trong các chủ đề trên tôi đã đề cập rằng tôi đã sử dụng một số tham số khi tôi tạo chỉ mục (đã hoạt động) lần trước. Vì vậy, đó là 'COLLATE NOCASE'. Tôi đã bỏ ra 6 giờ đồng hồ mà không có kết quả. Liên kết tốt đẹp, tôi cũng đã đọc nó, nhưng nó xuất hiện nó chỉ trượt khỏi sự chú ý của tôi. Cảm ơn, Homer! Bạn vừa mới cứu tôi là thần biết bao nhiêu thời gian. – nikans

+0

Tôi nghĩ bạn có nghĩa là 'PRAGMA case_sensitive_like = ON;' Như bạn đã nói, 'LIKE' không phân biệt chữ hoa chữ thường theo mặc định. Từ bài viết bạn liên kết đến: "Tối ưu hóa LIKE có thể xảy ra nếu cột được đặt tên bên trái toán tử được lập chỉ mục bằng cách sử dụng chuỗi đối chiếu BINARY được tích hợp sẵn và case_sensitive_like được bật." –

+0

Ah, đúng vậy. Tôi sẽ sửa chữa nó. Cảm ơn! –

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