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

Variazioni delle prestazioni delle query LIKE di PostgreSQL

FTS non supporta LIKE

La risposta precedentemente accettata non era corretta. La ricerca full-text con i suoi indici full-text non per il LIKE operatore, ha i suoi operatori e non funziona per stringhe arbitrarie. Funziona su parole basato su dizionari e stemming. lo fa supporta la corrispondenza dei prefissi per le parole , ma non con il LIKE operatore:

  • Ottieni una corrispondenza parziale dalla colonna TSVECTOR indicizzata GIN

Indici di trigramma per LIKE

Installa il modulo aggiuntivo pg_trgm che fornisce classi operatore per gli indici trigram GIN e GiST per supportare tutti LIKE e LIKE modelli , non solo quelli ancorati a sinistra:

Esempio di indice:

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

Oppure:

CREATE INDEX tbl_col_gist_trgm_idx ON tbl USING gist (col gist_trgm_ops);
  • Differenza tra indice GiST e GIN

Esempio di query:

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

Trigrammi? E le corde più corte?

Parole con meno di 3 lettere nei valori indicizzati funzionano ancora. Il manuale:

Si considera che ogni parola abbia due spazi preceduti e uno spazio suffisso quando si determina l'insieme di trigrammi contenuti nella stringa.

E i modelli di ricerca con meno di 3 lettere? Il manuale:

Per entrambi LIKE e le ricerche di espressioni regolari, tieni presente che un modello senza trigrammi estraibili degenererà in una scansione dell'indice completo.

Ciò significa che le scansioni dell'indice / bitmap funzionano ancora (i piani di query per l'istruzione preparata non si rompono), semplicemente non ti compreranno prestazioni migliori. In genere nessuna grossa perdita, dal momento che le stringhe di 1 o 2 lettere sono difficilmente selettive (più di una piccola percentuale delle corrispondenze della tabella sottostante) e il supporto dell'indice non migliorerebbe le prestazioni per cominciare, perché una scansione completa della tabella è più veloce.


text_pattern_ops per la corrispondenza del prefisso

Solo per ancorati a sinistra patterns (nessun carattere jolly iniziale) ottieni l'optimum con una classe di operatori adatta per un indice btree:text_pattern_ops o varchar_pattern_ops . Entrambe le funzionalità integrate di Postgres standard, nessun modulo aggiuntivo necessario. Performance simile, ma indice molto più piccolo.

Esempio di indice:

CREATE INDEX tbl_col_text_pattern_ops_idx ON tbl(col text_pattern_ops);

Esempio di query:

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

Oppure , se dovresti eseguire il tuo database con la 'C' locale (di fatto no locale), quindi tutto viene comunque ordinato in base all'ordine dei byte e un semplice indice btree con classe operatore predefinita fa il lavoro.

Maggiori dettagli, spiegazioni, esempi e collegamenti in queste risposte correlate su dba.SE:

  • Corrispondenza del modello con LIKE, SIMILAR TO o espressioni regolari in PostgreSQL
  • Come viene implementato LIKE?
  • Trovare rapidamente stringhe simili con PostgreSQL