Il pianificatore di query PostgreSQL è intelligente, ma non un'intelligenza artificiale. Per farlo, usa un indice su un'espressione usa la identica forma espressiva nella query.
Con un indice come questo:
CREATE INDEX t_a_lower_idx ON t (lower(substring(a, 1, 4)));
O più semplice in PostgreSQL 9.1:
CREATE INDEX t_a_lower_idx ON t (lower(left(a, 4)));
Usa questa query:
SELECT * FROM t WHERE lower(left(a, 4)) = 'abcd';
Che è funzionalmente equivalente al 100% a:
SELECT * FROM t WHERE lower(a) LIKE 'abcd%'
Oppure:
SELECT * FROM t WHERE a ILIKE 'abcd%'
Ma non :
SELECT * FROM t WHERE a LIKE 'abcd%'
Questa è una query diversa funzionalmente e hai bisogno di un diverso indice:
CREATE INDEX t_a_idx ON t (substring(a, 1, 4));
O più semplice con PostgreSQL 9.1:
CREATE INDEX t_a_idx ON t (left(a, 4));
E usa questa query:
SELECT * FROM t WHERE left(a, 4) = 'abcd';
Termini di ricerca ancorati a sinistra di lunghezza variabile
Senza distinzione tra maiuscole e minuscole. Indice:
Modifica :Quasi dimenticato:se esegui il tuo db con qualsiasi locale diverso da quello predefinito 'C', devi specifica esplicitamente la classe dell'operatore
- text_pattern_ops
nel mio esempio:
CREATE INDEX t_a_lower_idx
ON t (lower(left(a, <insert_max_length>)) text_pattern_ops);
Domanda:
SELECT * FROM t WHERE lower(left(a, <insert_max_length>)) ~~ 'abcdef%';
Può utilizzare l'indice ed è veloce quasi quanto la variante con lunghezza fissa.
Potresti essere interessato a questo post su dba.SE con maggiori dettagli sulla corrispondenza dei modelli
, in particolare l'ultima parte sugli operatori ~>=~
e ~<~
.