È proprio come hai letto da jjanes altrove:un indice di espressione viene considerato solo se l'espressione trova una corrispondenza esatta nel predicato della query. Il pianificatore di query di Postgres non è un'intelligenza artificiale. Vanderebbe rapidamente lo scopo di eseguire rapidamente query se la pianificazione richiede troppo tempo.
Puoi ottimizzare un po' il tuo indice, se questa è una consolazione. left()
è più semplice e veloce di substring()
:
CREATE INDEX record_changes_log_detail_old_value_ix_btree
ON record_changes_log_detail (left(old_value,1024) text_pattern_ops);
Inoltre, esiste una dimensione massima della riga di 2704 byte per gli indici btree, non un "limite di 2172 caratteri sugli alberi B" .
Ancora più importante, solo per i controlli di uguaglianza, come suggerisce la tua domanda, un indice btree su un valore hash usando md5(old_value)
o hashtext(old_value)
sarebbe molto più efficiente. Se lo fai, ricorda di difenderti dalle collisioni di hash così:
SELECT *
FROM record_changes_log_detail
WHERE hashtext(old_value) = hashtext('Gold Kerrison Neuro')
AND old_value = 'Gold Kerrison Neuro';
Il primo predicato offre un accesso rapido all'indice. Il secondo esclude i falsi positivi. Le collisioni dovrebbero essere estremamente rare. Ma possibile. E la possibilità cresce con le dimensioni del tavolo.
Correlati:
- La query SELECT con DISTINCT su una struttura a tabella per i grafici è molto lenta
- Qual è il tipo di dati ottimale per un campo MD5?
- Ricerca full-text in CouchDB
O un indice hash come quello che hai già considerato te stesso:
- Perché un indice hash Postgres 11 è così grande?
(Qui non devi preoccuparti delle collisioni di hash; gestite internamente.)