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

unaccent() che impedisce l'utilizzo dell'indice in Postgres

Variante IMMUTABLE di unaccent()

Per chiarire la disinformazione nella risposta errata attualmente accettata :
Gli indici delle espressioni consentono solo IMMUTABLE funzioni (per ovvi motivi) e unaccent() è solo STABLE . La soluzione che hai suggerito nel commento è anche problematico. Spiegazione dettagliata e una soluzione adeguata per quello :

A seconda del contenuto di tags->name può essere utile aggiungere unaccent() all'indice dell'espressione, ma è ortogonale alla domanda sul perché l'indice non è stato utilizzato:

Problema/soluzione reale

L'operatore LIKE nella tua query è sottilmente sbagliato (più probabilmente). non vuoi interpretare 'Weststrasse' come modello di ricerca, vuoi far corrispondere la stringa (normalizzata) così com'è. Sostituisci con = operatore e vedrai una scansione dell'indice (bitmap) con il tuo indice corrente, indipendentemente della volatilità della funzione di unaccent() :

SELECT * FROM germany.ways
WHERE lower(tags->'name') = lower(unaccent('unaccent','Weststrasse'))

Perché?

L'operando corretto di LIKE è un modello . Postgres non può utilizzare un semplice indice btree per la corrispondenza dei modelli ( si applicano eccezioni ). Un LIKE con una semplice stringa come modello (nessun carattere speciale) può essere ottimizzato con un controllo di uguaglianza sull'indice btree. Ma se ci sono caratteri speciali nella stringa, questo l'indice è uscito.

Se è presente un IMMUTABLE funzione a destra di LIKE , può essere valutato immediatamente e la suddetta ottimizzazione è ancora possibile. Per documentazione sulle Categorie di volatilità delle funzioni :

Lo stesso non è possibile con una minore volatilità della funzione (STABLE o VOLATILE ). Ecco perché la tua "soluzione" di fingere un IMMUTABLE unaccent() sembrava funzionare, ma sta davvero mettendo il rossetto su un maiale.

Per ribadire:

  • Se vuoi lavorare con LIKE e modelli, usa un indice trigram .
  • Se non vuoi lavorare con LIKE e modelli, utilizza l'operatore di uguaglianza =