2009/10/23 Alexandre - SetaDigital <[email protected]>
> Bom dia Pessoal... estou com um Problema
>
> Estou com uma base em UTF-8 com Indices, porem quando utilizo o LIKE ele
> nao utiliza o indice na pesquisa... o que pode ser???
>
>
Se você não usou uma Classe de Operadores adequada ele não irá utilizar
índices mesmo.
Para fazer uso de índices com um LIKE (ou expressão regular) você deve
definir uma Classe de Operador especial na criação do seu índice, veja:
postg...@bdteste=# create table foo(nome text);
CREATE TABLE
postg...@bdteste=# create index foo_nome_in on foo(nome);
CREATE INDEX
postg...@bdteste=# insert into foo(nome) values ('Fabrizio'), ('Ricardo'),
('Alberto'), ('Francisco'), ('Amanda'), ('Roberta'), ('Raysa'), ('Daniela');
INSERT 0 8
postg...@bdteste=# select * from foo where nome like 'A%';
nome
---------
Alberto
Amanda
(2 rows)
postg...@bdteste=# set enable_seqscan to off ;
SET
Estou setando essa variável SOMENTE para forçar o planejador a usar índice,
senão ele SEMPRE irá fazer seqscan na tabela em funcao da mesma ser muito
pequena... em ambiente de produção recomendo deixar essa opção como "on"...
não devemos tentar ser mais espertos que o planejador porque com certeza não
somos... hehehe
Agora um explain na query anterior...
postg...@bdteste=# explain select * from foo where nome like 'A%';
QUERY PLAN
--------------------------------------------------------------------
Seq Scan on foo (cost=100000000.00..100000025.38 rows=6 width=32)
Filter: (nome ~~ 'A%'::text)
(2 rows)
Com o índice criado normalmente não usou índice... agora vamos recriar o
índice usando a Classe de Operador "varchar_pattern_ops" conforme indica o
manual [1]:
postg...@bdteste=# drop index foo_nome_in;
DROP INDEX
postg...@bdteste=# create index foo_nome_in on foo(nome
varchar_pattern_ops);
CREATE INDEX
Novamente o explain...
postg...@bdteste=# explain select * from foo where nome like 'A%';
QUERY
PLAN
------------------------------------------------------------------------------------------
Index Scan using foo_nome_in on foo (cost=0.00..8.27 rows=1 width=32)
Index Cond: ((nome ~>=~ 'A'::character varying) AND (nome ~<~
'B'::character varying))
Filter: (nome ~~ 'A%'::text)
(3 rows)
Agora um último detalhe, somente funcionará o LIKE se vc informar o INICIO
da string de pesquisa, se quiser fazer algo do tipo LIKE '%A%' ele não irá
usar índice mesmo:
postg...@bdteste=# explain select * from foo where nome like '%A%';
QUERY PLAN
--------------------------------------------------------------------
Seq Scan on foo (cost=100000000.00..100000001.10 rows=8 width=32)
Filter: (nome ~~ '%A%'::text)
(2 rows)
Espero ter ajudado...
[1] http://www.postgresql.org/docs/8.4/interactive/indexes-opclass.html
Cordialmente,
--
Fabrízio de Royes Mello
>> Blog sobre TI: http://fabriziomello.blogspot.com
_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral