PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Schwankungen der PostgreSQL LIKE-Abfrageleistung

FTS unterstützt LIKE nicht

Die zuvor akzeptierte Antwort war falsch. Die Volltextsuche mit ihren Volltextindizes ist nicht für das LIKE Operator überhaupt, er hat seine eigenen Operatoren und funktioniert nicht für beliebige Strings. Es arbeitet mit Wörtern basierend auf Wörterbüchern und Wortstammbildung. Das tut es unterstützt Präfix-Matching für Wörter , aber nicht mit dem LIKE Betreiber:

  • Teilweise Übereinstimmung aus GIN-indizierter TSVECTOR-Spalte abrufen

Trigramm-Indizes für LIKE

Installieren Sie das Zusatzmodul pg_trgm die Operatorklassen für GIN- und GiST-Trigrammindizes bereitstellt, um alle LIKE zu unterstützen und ILIKE Muster , 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);
  • Unterschied zwischen GiST- und GIN-Index

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 noch. Das Handbuch:

Es wird davon ausgegangen, dass jedes Wort zwei vorangestellte Leerzeichen und ein vorangestelltes Leerzeichen enthält, wenn die Menge der in der Zeichenfolge enthaltenen Trigramme bestimmt wird.

Und Suchmuster mit weniger als 3 Buchstaben? Das Handbuch:

Für beide LIKE und Suchen mit regulären Ausdrücken, denken Sie daran, dass ein Muster ohne extrahierbare Trigramme zu einem vollständigen Index-Scan degenerieren wird.

Das bedeutet, dass Index- / Bitmap-Index-Scans immer noch funktionieren (Abfragepläne für vorbereitete Anweisungen werden nicht unterbrochen), es wird Ihnen nur keine bessere Leistung bringen. Typischerweise kein großer Verlust, da 1- oder 2-Buchstaben-Strings kaum selektiv sind (mehr als ein paar Prozent der zugrunde liegenden Tabelle stimmen überein) und die Indexunterstützung die Leistung von vornherein nicht verbessern würde, da ein vollständiger Tabellenscan schneller ist.


text_pattern_ops für den Präfixabgleich

Für nur links verankert Muster (keine führenden Platzhalter) erhalten Sie mit einer geeigneten Operatorklasse für einen btree-Index optimal:text_pattern_ops oder varchar_pattern_ops . Beides integrierte 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 , wenn Sie Ihre Datenbank mit dem 'C' betreiben sollen Gebietsschema (effektiv kein locale), dann wird sowieso alles nach Byte-Reihenfolge sortiert und ein einfacher btree-Index mit Standardoperatorklasse erledigt die Arbeit.

Weitere Details, Erklärungen, Beispiele und Links in diesen verwandten Antworten auf dba.SE:

  • Mustervergleich mit LIKE, SIMILAR TO oder regulären Ausdrücken in PostgreSQL
  • Wie wird LIKE implementiert?
  • Ähnliche Zeichenketten mit PostgreSQL schnell finden