PostgreSQL-frågeplaneraren är smart, men inte en AI. För att få det att använda ett index på ett uttryck använd exakt samma uttrycksform i frågan.
Med ett index som detta:
CREATE INDEX t_a_lower_idx ON t (lower(substring(a, 1, 4)));
Eller enklare i PostgreSQL 9.1:
CREATE INDEX t_a_lower_idx ON t (lower(left(a, 4)));
Använd den här frågan:
SELECT * FROM t WHERE lower(left(a, 4)) = 'abcd';
Vilket är 100 % funktionellt likvärdigt med:
SELECT * FROM t WHERE lower(a) LIKE 'abcd%'
Eller:
SELECT * FROM t WHERE a ILIKE 'abcd%'
Men inte :
SELECT * FROM t WHERE a LIKE 'abcd%'
Detta är en funktionellt annan fråga och du behöver en annan index:
CREATE INDEX t_a_idx ON t (substring(a, 1, 4));
Eller enklare med PostgreSQL 9.1:
CREATE INDEX t_a_idx ON t (left(a, 4));
Och använd den här frågan:
SELECT * FROM t WHERE left(a, 4) = 'abcd';
Vänsterförankrade söktermer med variabel längd
Fallet okänslig. Index:
Redigera :Glömde nästan:Om du kör din db med någon annan lokalitet än standard "C", måste du ange operatorklassen uttryckligen
- text_pattern_ops
i mitt exempel:
CREATE INDEX t_a_lower_idx
ON t (lower(left(a, <insert_max_length>)) text_pattern_ops);
Fråga:
SELECT * FROM t WHERE lower(left(a, <insert_max_length>)) ~~ 'abcdef%';
Kan utnyttja indexet och är nästan lika snabb som varianten med fast längd.
Du kanske är intresserad av detta inlägg på dba.SE med mer information om mönstermatchning
, speciellt den sista delen om operatorerna ~>=~
och ~<~
.