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

Responder a