2012-08-25 11 views
6

ich eine Abfrage mit einer Reihe von Test haben Felder etwas wie folgt aus:Postgresql ILIKE gegen TSEARCH

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

Die Spalten so ziemlich alle varchar (50) oder so sind. Jetzt verstehe ich, um die Leistung zu verbessern. Ich sollte die Felder indizieren, auf denen die Suche funktioniert. Sollte ich darüber nachdenken, ILIKE durch TSEARCH komplett zu ersetzen?

Antwort

15

Eine Volltextsuche ist nicht identisch mit einer "enthält" Abfrage. Es stößt Wörter usw. an, so dass Sie "Autos" gegen "Auto" abstimmen können.

Wenn Sie wirklich eine schnelle ILIKE wollen, dann hilft kein Standard-Datenbankindex oder FTS. Glücklicherweise kann das Modul pg_trgm das tun.

+0

pg_trgm ist sehr hilfreich. Für Django-Benutzer: Index auf 'Upper (your_text_field)', weil Django 'upper (x) wie obere (y)' Abfragen anstelle von 'ilike' ausgibt. Wenn das Feld ohne "Upper" indexiert wird, wird der Index in diesen Abfragen nicht verwendet. – Risadinha

5

Eine Sache, die sehr wichtig ist: NO B-Tree-Index jemals diese Art der Suche verbessern:

where field ilike '%SOMETHING%' 

Was ich sage ist, dass, wenn Sie tun, um eine:

create index idx_name on some_table(field); 

Der einzige Zugang, den Sie verbessern werden, ist where field like 'something%'. (wenn Sie nach Werten suchen, die mit einem Literal beginnen). Sie erhalten also keinen Vorteil, wenn Sie in diesem Fall einen regulären Index zur Spalte field hinzufügen.

Wenn Sie Ihre Reaktionszeit für die Suche verbessern müssen, verwenden Sie unbedingt FULL TEXT SEARCH.

+0

Sie haben Recht, dass kein B-Tree diese Suche verbessert, aber PostgreSQL kann andere Indextypen verwenden, um eine '% foobar%' Bedingung zu unterstützen (siehe Richards Antwort) –

3

ein wenig Hinzufügen was die anderen gesagt haben.

Zuerst können Sie einen Index nicht wirklich basierend auf einem Wert in der Mitte der Zeichenfolge verwenden. Indizes sind im Allgemeinen Baumsuchvorgänge, und Sie haben keine Möglichkeit zu wissen, ob Ihre Suche schneller ist als nur das Scannen der Tabelle, sodass PostgreSQL standardmäßig auf einen Seq-Scan setzt. Indizes werden nur verwendet, wenn sie dem ersten Teil der Zeichenfolge entsprechen. Also:

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

kann einen Index verwenden, aber like '%44354456%' nicht.

Im Allgemeinen verwenden wir in LedgerSMB beide, je nachdem, welche Art von Suche wir durchführen. Möglicherweise sehen Sie eine Suche wie:

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

So sind diese sehr unterschiedlich. Verwenden Sie jeden, wo es am sinnvollsten ist.

+1

Ich stimme zu, dass es nicht genug Informationen gibt, um sicher zu stellen, ob Trigramm oder Tsearch geeigneter ist, aber die eine oder andere (oder möglicherweise eine Kombination) scheint angezeigt. – kgrittn

Verwandte Themen