FTS unterstützt nicht LIKE
Die zuvor akzeptierte Antwort war falsch. Die Volltextsuche mit ihren Volltextindizes ist überhaupt nicht für den LIKE
Operator, sie hat ihre eigenen Operatoren und funktioniert nicht für beliebige Zeichenfolgen. Es arbeitet mit Wörtern, die auf Wörterbüchern und Stemming basieren. Es tut Unterstützung für Worte Abgleich von Präfixen , aber nicht mit dem LIKE
Betreiber:
Trigrammindizes für LIKE
Installieren Sie das zusätzliche Modul pg_trgm
, das Operatorklassen für GIN- und GiST-Trigrammindizes bereitstellt , um alle LIKE
und ILIKE
Muster zu unterstützen , nicht nur links verankerte:
Beispielindex:
CREATE INDEX tbl_col_gin_trgm_idx ON tbl USING gin (col gin_trgm_ops);
Oder:
CREATE INDEX tbl_col_gist_trgm_idx ON tbl USING gist (col gist_trgm_ops);
Beispielabfrage:
SELECT * FROM tbl WHERE col LIKE '%foo%'; -- leading wildcard
SELECT * FROM tbl WHERE col ILIKE '%foo%'; -- works case insensitively as well
Trigramme? Was ist mit kürzeren Saiten?
Wörter mit weniger als 3 Buchstaben in indizierten Werten funktionieren weiterhin. Das Handbuch:
Bei jedem Wort werden zwei Leerzeichen und ein Leerzeichen vorangestellt, wenn die in der Zeichenfolge enthaltene Menge von Trigrammen bestimmt wird.
Und Suchmuster mit weniger als 3 Buchstaben? Das Handbuch:
Für beide LIKE
und regulären Ausdrücken sucht, bedenken Sie, dass ein Muster ohne ausziehbare trigrams zu einem Full-Index - Scan degeneriert wird.
Das bedeutet, dass Index- / Bitmap-Index-Scans immer noch funktionieren (Abfragepläne für vorbereitete Anweisungen werden nicht unterbrochen). Sie erhalten einfach keine bessere Leistung. Normalerweise kein großer Verlust, da Zeichenfolgen mit 1 oder 2 Buchstaben kaum selektiv sind (mehr als ein paar Prozent der zugrunde liegenden Tabellenübereinstimmungen) und die Indexunterstützung die Leistung zunächst nicht verbessern würde, da ein vollständiger Tabellenscan schneller ist.
text_pattern_ops
für Präfixabgleich
Für nur links verankerte Muster (kein führender Platzhalter) erhalten Sie das Optimum mit einer geeigneten Operatorklasse für einen btree-Index: text_pattern_ops
oder varchar_pattern_ops
. Beide integrierten Funktionen von Standard-Postgres, kein zusätzliches Modul erforderlich. Ähnliche Leistung, aber viel kleinerer Index.
Beispielindex:
CREATE INDEX tbl_col_text_pattern_ops_idx ON tbl(col text_pattern_ops);
Beispielabfrage:
SELECT * FROM tbl WHERE col LIKE 'foo%'; -- no leading wildcard
Oder sollten , wenn Sie Ihre Datenbank mit dem laufen ‚C‘ locale (effektiv keine locale), dann ist sowieso alles nach Byte - Reihenfolge sortiert und ein einfaches btree Index mit Standardoperatorklasse macht den Job.
Weitere Details, Erklärungen, Beispiele und Links in diesen verwandten Antworten auf dba.SE:
pg_trgm
benötigen Sie eine Abfragezeichenfolge mit mindestens 3 Zeichen Länge, die beispielsweisefo%
nicht den Index trifft, sondern stattdessen einen Scan durchführt. Etwas zu beachten.Möglicherweise sind die schnellen Muster verankerte Muster, bei denen zwischen Groß- und Kleinschreibung unterschieden wird und Indizes verwendet werden können. Das heißt, am Anfang der Übereinstimmungszeichenfolge befindet sich kein Platzhalter, sodass der Executor einen Indexbereichsscan verwenden kann. ( Der entsprechende Kommentar in den Dokumenten ist hier ) Lower und ilike verlieren auch Ihre Fähigkeit, den Index zu verwenden, es sei denn, Sie erstellen speziell einen Index für diesen Zweck (siehe Funktionsindizes ).
Wenn Sie in der Mitte des Feldes nach Zeichenfolgen suchen möchten, sollten Sie sich Volltext- oder Trigrammindizes ansehen . Der erste befindet sich im Postgres-Kern, der andere ist in den Contrib-Modulen verfügbar.
quelle
Sie können Wildspeed installieren , einen anderen Indextyp in PostgreSQL. Wildspeed funktioniert mit% word% Wildcards, kein Problem. Der Nachteil ist die Größe des Index, dies kann groß sein, sehr groß.
quelle
Führen Sie die unten genannte Abfrage aus, um die Leistung der LIKE-Abfrage in postgresql zu verbessern. Erstellen Sie einen solchen Index für größere Tabellen:
quelle
Für das, was es wert ist, wird Django ORM in der Regel
UPPER(text)
für alleLIKE
Abfragen verwendet, um die Groß- und Kleinschreibung nicht zu berücksichtigen.Das Hinzufügen eines Index
UPPER(column::text)
hat mein System im Gegensatz zu anderen Dingen erheblich beschleunigt.Soweit führende%, ja, das wird keinen Index verwenden. In diesem Blog finden Sie eine gute Erklärung:
https://use-the-index-luke.com/sql/where-clause/searching-for-ranges/like-performance-tuning
quelle
Ich hatte kürzlich ein ähnliches Problem mit einer Tabelle mit 200000 Datensätzen und muss wiederholte LIKE-Abfragen durchführen. In meinem Fall wurde die gesuchte Zeichenfolge behoben. Andere Bereiche waren unterschiedlich. Dadurch konnte ich umschreiben:
wie
Ich war begeistert, als die Anfragen schnell zurückkamen und bestätigten, dass der Index verwendet wird mit
EXPLAIN ANALYZE
:quelle
Ihre ähnlichen Abfragen können die von Ihnen erstellten Indizes wahrscheinlich nicht verwenden, weil:
1) Ihre LIKE-Kriterien beginnen mit einem Platzhalter.
2) Sie haben eine Funktion mit Ihren LIKE-Kriterien verwendet.
quelle
Wann immer Sie eine Klausel für eine Spalte mit Funktionen wie LIKE, ILIKE, Upper, Lower usw. verwenden, berücksichtigen Postgres Ihren normalen Index nicht. Es wird ein vollständiger Scan der Tabelle durchgeführt, die durch jede Zeile geht, und daher wird es langsam sein.
Der richtige Weg wäre, einen neuen Index entsprechend Ihrer Abfrage zu erstellen. Zum Beispiel, wenn ich eine Spalte ohne Groß- und Kleinschreibung abgleichen möchte und meine Spalte ein Varchar ist. Dann können Sie es so machen.
Wenn Ihre Spalte ein Text ist, tun Sie dies auch
Ebenso können Sie die obere Funktion in eine beliebige andere Funktion ändern.
quelle