2012-08-25 15 views
6

Ho una domanda con una serie di test di campi o meno così:PostgreSQL ILIKE contro TSEARCH

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

Le colonne sono più o meno tutto varchar (50) o giù di lì. Ora capisco per migliorare le prestazioni dovrei indicizzare i campi su cui opera la ricerca. Dovrei considerare di sostituire ILIKE con TSEARCH completamente?

risposta

15

Un'impostazione di ricerca di testo completo non è identica a una query "contiene" come. Si tratta di parole ecc. In modo da poter abbinare "auto" a "auto".

Se si desidera un ILIKE veloce, non sarà possibile utilizzare alcun indice di database standard o FTS. Fortunatamente, il modulo pg_trgm può farlo.

+0

pg_trgm è molto utile. Per gli utenti di Django: indice su 'upper (your_text_field)' perché Django emette le query 'upper (x) like upper (y) 'invece di' ilike'. Se il campo è indicizzato senza 'upper', l'indice non verrà utilizzato in tali query. – Risadinha

5

Una cosa che è molto importante: NO B-ALBERO INDEX potrà mai migliorare questo tipo di ricerca:

where field ilike '%SOMETHING%' 

Quello che sto dicendo è che se si fa un:

create index idx_name on some_table(field); 

L'unico accesso che migliorerai è where field like 'something%'. (quando cerchi valori che iniziano con un valore letterale). In questo caso, non otterrai alcun vantaggio aggiungendo un indice regolare alla colonna field.

Se è necessario migliorare il tempo di risposta della ricerca, considerare sicuramente l'uso di RICERCA TESTO COMPLETO.

+0

Hai ragione che nessun B-Tree migliorerà la ricerca, ma PostgreSQL può usare altri tipi di indice per supportare una condizione% fobar% '(vedi la risposta di Richard) –

3

Aggiunta di un po 'di quanto gli altri hanno detto.

Per prima cosa non è possibile utilizzare un indice basato su un valore nel mezzo della stringa. Gli indici sono generalmente ricerche sugli alberi, e non hai modo di sapere se la tua ricerca sarà più veloce della semplice scansione della tabella, quindi PostgreSQL imposterà automaticamente una scansione seq. Gli indici saranno utilizzati solo se corrispondono alla prima parte della stringa. Quindi:

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

può utilizzare un indice, ma non riesco a like '%44354456%'.

In generale in LedgerSMB utilizziamo entrambi, a seconda del tipo di ricerca che stiamo eseguendo. Si potrebbe vedere una ricerca come:

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

Quindi questi sono molto diversi. Usali ognuno dove ha più senso.

+1

Concordo sul fatto che non ci siano informazioni sufficienti per essere sicuri che il trigramma o la ricerca siano più appropriati, ma l'uno o l'altro (o eventualmente una combinazione) sembra indicato. – kgrittn