sql >> Database teknologi >  >> RDS >> PostgreSQL

Variationer i PostgreSQL LIKE-forespørgselsydeevne

FTS understøtter ikke LIKE

Det tidligere accepterede svar var forkert. Fuld tekstsøgning med dens fulde tekstindeks er ikke for LIKE operatør overhovedet, den har sine egne operatører og virker ikke for vilkårlige strenge. Det fungerer på ord baseret på ordbøger og stemming. Det gør understøtter præfiksmatchning for ord , men ikke med LIKE operatør:

  • Få delvis match fra GIN-indekseret TSVECTOR-kolonne

Trigramindekser for LIKE

Installer det ekstra modul pg_trgm som giver operatørklasser til GIN- og GiST-trigramindekser for at understøtte alle LIKE og ILIKE mønstre , ikke kun venstreforankrede:

Eksempelindeks:

CREATE INDEX tbl_col_gin_trgm_idx  ON tbl USING gin  (col gin_trgm_ops);

Eller:

CREATE INDEX tbl_col_gist_trgm_idx ON tbl USING gist (col gist_trgm_ops);
  • Forskel mellem GiST og GIN-indeks

Eksempelforespørgsel:

SELECT * FROM tbl WHERE col LIKE '%foo%';   -- leading wildcard
SELECT * FROM tbl WHERE col ILIKE '%foo%';  -- works case insensitively as well

Trigrammer? Hvad med kortere strenge?

Ord med mindre end 3 bogstaver i indekserede værdier fungerer stadig. Manualen:

Hvert ord anses for at have to mellemrum foran og et mellemrum, når man bestemmer det sæt af trigrammer, der er indeholdt i strengen.

Og søgemønstre med mindre end 3 bogstaver? Manualen:

For begge LIKE og almindelige udtrykssøgninger, skal du huske på, at et mønster uden udtrækbare trigrammer vil degenerere til en fuldindeksscanning.

Det betyder, at indeks-/bitmap-indeksscanninger stadig virker (forespørgselsplaner for udarbejdet erklæring vil ikke bryde), det vil bare ikke give dig bedre ydeevne. Typisk ikke noget stort tab, da strenge på 1 eller 2 bogstaver næppe er selektive (mere end et par procent af de underliggende tabelmatches), og indeksstøtte ville ikke forbedre ydeevnen til at begynde med, fordi en fuld tabelscanning er hurtigere.


text_pattern_ops for præfiksmatchning

For kun venstre forankret mønstre (ingen indledende jokertegn) får du det optimale med en passende operatorklasse til et btree-indeks:text_pattern_ops eller varchar_pattern_ops . Begge indbyggede funktioner i standard Postgres, intet ekstra modul nødvendigt. Lignende ydeevne, men meget mindre indeks.

Eksempelindeks:

CREATE INDEX tbl_col_text_pattern_ops_idx ON tbl(col text_pattern_ops);

Eksempelforespørgsel:

SELECT * FROM tbl WHERE col LIKE 'foo%';  -- no leading wildcard

Eller , hvis du skulle køre din database med 'C' landestandard (effektivt nej locale), så bliver alt alligevel sorteret efter byte-rækkefølge, og et almindeligt btree-indeks med standardoperatorklasse klarer jobbet.

Flere detaljer, forklaringer, eksempler og links i disse relaterede svar på dba.SE:

  • Mønstermatching med LIKE, SIMILAR TO eller regulære udtryk i PostgreSQL
  • Hvordan implementeres LIKE?
  • Hurtigt at finde lignende strenge med PostgreSQL


  1. SQL-forespørgsel for at finde post med ID, der ikke er i en anden tabel

  2. Installer flere MySQL-instanser på en Linux-server - brug en separat MySQL-konfigurationsfil

  3. hvordan man finder alle indekser og deres kolonner for tabeller, visninger og synonymer i Oracle

  4. Hvad er MariaDB? Hvordan virker MariaDB?