2012-08-25 28 views
6

Mam zapytanie z numerem badania pola tak:Postgresql ILIKE kontra pełnotekstowego

SELECT * FROM some-table 
    WHERE field1 ILIKE "%thing%" 
    OR field2 ILIKE "%thing" 
    OR field3 ILIKE "%thing"; 

Kolumny są prawie wszystkich varchar (50) lub w tej okolicy. Rozumiem, że w celu poprawy wydajności powinienem indeksować pola, na których działa wyszukiwanie. Czy powinienem rozważyć całkowitą zamianę ILIKE na TSEARCH?

Odpowiedz

15

Konfiguracja wyszukiwania pełnotekstowego nie jest identyczna z zapytaniem "zawiera". Wynikają ze słów itp., Więc możesz dopasować "samochody" do "samochodu".

Jeśli naprawdę chcesz szybki ILIKE, to nie pomoże żaden standardowy indeks bazy danych ani FTS. Na szczęście moduł pg_trgm może to zrobić.

+0

pg_trgm jest bardzo pomocny. Dla użytkowników Django: indeks na 'upper (your_text_field)', ponieważ Django wydaje 'upper (x) like upper (y)' queries zamiast 'ilike'. Jeśli pole jest indeksowane bez 'upper', indeks nie będzie używany w tych zapytaniach. – Risadinha

5

Jedna rzecz, która jest bardzo ważna: NR B-TREE INDEX nigdy poprawy tego rodzaju wyszukiwania:

where field ilike '%SOMETHING%' 

co mówię, jest to, że jeśli zrobić:

create index idx_name on some_table(field); 

Jedyny dostęp, który poprawisz, to where field like 'something%'. (gdy szukasz wartości zaczynających się od literału). Tak więc, nie dostaniesz żadnej korzyści, dodając w tym przypadku regularny indeks do kolumny field.

Jeśli potrzebujesz poprawić czas odpowiedzi na wyszukiwanie, zdecydowanie rozważ skorzystanie z PEŁNEGO TEKSTU WYSZUKIWANIA.

+0

Masz rację, że żadne B-drzewo nie poprawi tego wyszukiwania, ale PostgreSQL może używać innych typów indeksu do obsługi warunku '% foobar%' (patrz odpowiedź Richarda) –

3

Dodawanie trochę do tego, co mówili inni.

Po pierwsze nie można tak naprawdę użyć indeksu opartego na wartości w środku ciągu. Indeksy są ogólnie przeszukiwaniami drzewa i nie masz możliwości sprawdzenia, czy wyszukiwanie będzie szybsze niż skanowanie tabeli, więc PostgreSQL będzie domyślnie skanować sekwencyjnie. Indeksy będą używane tylko wtedy, gdy pasują do pierwszej części ciągu. Więc:

SELECT * FROM invoice 
    WHERE invoice_number like 'INV-2012-435%' 

może użyć indeksu ale like '%44354456%' nie może.

Ogólnie w LedgerSMB używamy obu, w zależności od tego, jakiego rodzaju wyszukiwania wykonujemy. Możesz zobaczyć wyszukiwanie takie jak:

select * from parts 
    WHERE partnumber ilike ? || '%' 
    and plainto_tsquery(get_default_language(), ?) @@ description; 

Są one bardzo różne. Użyj każdego, w którym ma to największy sens.

+1

Zgadzam się, że nie ma wystarczających informacji, aby upewnić się, że trygram lub badanie są bardziej odpowiednie, ale jedna lub druga (lub ewentualnie kombinacja) wydaje się wskazana. – kgrittn