sql >> Databasteknik >  >> RDS >> PostgreSQL

PostgreSQL LIKE-frågeprestandavariationer

FTS stöder inte LIKE

Det tidigare accepterade svaret var felaktigt. Fulltextsökning med dess fulltextindex är inte för LIKE operatör alls, den har sina egna operatörer och fungerar inte för godtyckliga strängar. Det fungerar på ord baserad på ordböcker och stemming. Det gör stöder prefixmatchning för ord , men inte med LIKE operatör:

  • Få partiell matchning från GIN-indexerad TSVECTOR-kolumn

Trigramindex för LIKE

Installera tilläggsmodulen pg_trgm som tillhandahåller operatörsklasser för GIN- och GiST-trigramindex för att stödja alla LIKE och ILIKE mönster , inte bara vänsterförankrade:

Exempelindex:

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);
  • Skillnad mellan GiST och GIN-index

Exempelfråga:

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

Trigram? Hur är det med kortare strängar?

Ord med färre än 3 bokstäver i indexerade värden fungerar fortfarande. Manualen:

Varje ord anses ha två mellanslag före och ett mellanslag vid fastställande av uppsättningen trigram i strängen.

Och sökmönster med mindre än 3 bokstäver? Manualen:

För båda LIKE och sökningar med reguljära uttryck, kom ihåg att ett mönster utan extraherbara trigram kommer att degenerera till en fullindexskanning.

Det betyder att index-/bitmappsindexsökningar fortfarande fungerar (frågeplaner för förberedda uttalanden kommer inte att gå sönder), det kommer bara inte att ge dig bättre prestanda. Vanligtvis ingen stor förlust, eftersom strängar på 1 eller 2 bokstäver knappast är selektiva (mer än några procent av de underliggande tabellmatchningarna) och indexstöd inte skulle förbättra prestandan till att börja med, eftersom en fullständig tabellsökning är snabbare.


text_pattern_ops för prefixmatchning

För bara vänsterankrade mönster (inget inledande jokertecken) får du det optimala med en lämplig operatorklass för ett btree-index:text_pattern_ops eller varchar_pattern_ops . Båda inbyggda funktionerna i standard Postgres, ingen extra modul behövs. Liknande prestanda, men mycket mindre index.

Exempelindex:

CREATE INDEX tbl_col_text_pattern_ops_idx ON tbl(col text_pattern_ops);

Exempelfråga:

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

Eller , om du skulle köra din databas med 'C' locale (effektivt nej locale), så sorteras allt enligt byteordning ändå och ett vanligt btree-index med standardoperatörsklass gör jobbet.

Mer detaljer, förklaringar, exempel och länkar i dessa relaterade svar på dba.SE:

  • Mönstermatchning med LIKE, SIMILAR TO eller reguljära uttryck i PostgreSQL
  • Hur implementeras LIKE?
  • Snabbt att hitta liknande strängar med PostgreSQL


  1. SQLite JSON_INSERT()

  2. Ge en msdb-användaråtkomst till en databaspostprofil i SQL Server (T-SQL)

  3. CTE-fel:Typerna matchar inte mellan ankaret och den rekursiva delen

  4. Hur man skapar ett beräknat fält i en Microsoft Access-fråga