2012-10-21 8 views
5

Próbowałem uzyskać sqlite, aby użyć indeksu z niczym bez skutku. Spróbowałem zebrać nocase i wciąż nie miałem szczęścia. Każdy ma jakieś pomysły, jak uzyskać sqlite, aby zrobić jak uderzenie w indeks. Dzięki z górysqlite nie używa indeksu z podobnym zapytaniem

DROP TABLE IF EXISTS "test"; 
DROP TABLE IF EXISTS "test2"; 
DROP TABLE IF EXISTS "test3"; 
create table test(name TEXT COLLATE NOCASE); 
create table test2(name TEXT); 
create table test3(name TEXT); 
create index idx_test_name on test(name); 
create index idx_test2_name on test2(name); 
create index idx_test3_name on test3(name COLLATE NOCASE); 
insert into test(name) values('dan'); 
insert into test2(name) values('dan'); 
insert into test3(name) values('dan'); 
--explain query plan select * from test where name like 'test%' 
-- explain query plan select * from test2 where name like 'test%' 
-- explain query plan select * from test3 where name like 'test%' 
+0

Posiadanie indeksu nie gwarantuje, że zostanie użyty. –

Odpowiedz

1

W SQLite 3.6.23.1, wskaźnik na test stosuje się:

> explain query plan select * from test where name like 'test%'; 
TABLE test WITH INDEX idx_test_name 

> explain query plan select * from test2 where name like 'test%'; 
TABLE test2 

> explain query plan select * from test3 where name like 'test%'; 
TABLE test3 

W wersji rozwojowej SQLite 3.7.15 oba test 'S test3' indeksy S są stosowane (indeks na test2 służy do skanowania, nie szukając):

> explain query plan select * from test where name like 'test%'; 
SEARCH TABLE test USING COVERING INDEX idx_test_name (name>? AND name<?) (~31250 rows) 

> explain query plan select * from test2 where name like 'test%'; 
SCAN TABLE test2 USING COVERING INDEX idx_test2_name (~500000 rows) 

> explain query plan select * from test3 where name like 'test%'; 
SEARCH TABLE test3 USING COVERING INDEX idx_test3_name (name>? AND name<?) (~31250 rows) 

Więc odpowiedź jest aktualizacja SQLite.

+0

Dzięki temu użyłem rozszerzenia firefox do przetestowania, która była starszą wersją. Używanie nowszej wersji działa – aboutme

11

Cytat z listy sqlite poczty (http://www.mail-archive.com/[email protected]/msg27760.html)

LIKE jest CASE- niewrażliwy domyślnie. Aby użyć indeksu, musisz ustawić wielkość liter bez względu na wielkość liter:

CREATE INDEX nazwa_testu ON test (nazwa COLLATE NOCASE);

lub dokonać JAK rozróżniana:

PRAGMA case_sensitive_like = 1;

+0

Także na dokumentach http://www.sqlite.org/optoverview.html – Himanshu

+0

Cześć, dziękuję za odpowiedzi everyones, jednak po przetestowaniu nocowania na indeksie indeks nadal nie jest używany.Ive zaktualizował mój przykładowy kod test3, aby przetestować scenariusz, jeśli ktoś chce spróbować. Jakieś inne pomysły? – aboutme

0

Z docs:

Warunki, które składają się z operatorem LIKE lub GLOB mogą czasami być wykorzystywane do ograniczania indeksów. Istnieje wiele warunków dotyczących tego użycia:

  • Lewa strona operatora LIKE lub GLOB musi być nazwą indeksowanej kolumny z powinowactwem TEXT.
  • Prawa strona parametru LIKE lub GLOB musi być literałem łańcuchowym lub parametrem powiązanym z literałem łańcuchowym, który nie rozpoczyna się od z symbolem wieloznacznym.
  • Klauzula ESCAPE nie może pojawić się w operatorze LIKE.
  • Wbudowane funkcje używane do implementacji LIKE i GLOB nie mogły zostać przeciążone za pomocą funkcji API sqlite3_create_function().
  • W przypadku operatora GLOB kolumna musi zostać zaindeksowana za pomocą wbudowanej sekwencji zestawiania BINARY.
  • Dla operatora LIKE, jeśli włączony jest tryb case_sensitive_like, kolumna musi być indeksowana przy użyciu BINARNEJ sekwencji sortowania lub jeśli tryb case_sensitive_like jest wyłączony, kolumna musi zindeksować przy użyciu wbudowanej sekwencji zestawiania NOCASE.
Powiązane problemy