On 06-12-2013 08:45, Matheus de Oliveira wrote:

2013/12/5 Matheus Saraiva <[email protected]
<mailto:[email protected]>>

    Tendo os campos A, B, C

    digamos que eu crie um índice composto (A, B) e também crie um
    índice simples ( C ). Sei que se for feita uma consulta apenas com o
    campo A o indice (A, B) será usado. Mas se eu fizer uma consulta com
    filtro em (C, A), os dois índices separados serão usados?


Eles poderão ser usados sim. Mas, como sempre, depende. Nesse caso irá
depender de quão seletivo seu filtro é para cada campo.

Vamos pensar num exemplo simples. Numa tabela com 10 milhões de
registros, supondo que você faça:

     SELECT ... FROM foo WHERE a = 10 AND c = 15;

O PostgreSQL vai poder usar qualquer um dos índices que você criou. Mas
para decidir qual (ou quais) usará, ele tentará "adivinhar" quantos
registros cada filtro retornará, da seguinte forma:

1. Quantas tuplas somente o filtro `a = 10` retorna?
2. Quantas tuplas somente o filtro `c = 15` retorna?
3. Quantas tuplas ambos filtros, `a = 10 AND c = 15` retornam?

Esse "adivinhar" é baseado nas estatísticas do banco de dados (vamos
deixar essa pra outro momento). Vamos supor alguns exemplos baseados nos
itens acima:

1. Existem aproximadamente 1 milhão de registros com `a = 10`.
2. Existem aproximadamente 5 mil registros com `c = 15`.
3. Existem aproximadamente mil registros com ambos.

Nesse caso podemos dizer (um chute) que o PostgreSQL iria preferir usar
somente o índice em (C). Com ele iria encontrar os 5 mil registros onde
`c = 15`, em seguida, buscaria (da tabela mesmo) os (meros) mil
registros onde `a = 10`. Vale mais a pena do que o trabalho extra para
navegar nos dois índices. Agora, se pensarmos diferente:

1. Existem aproximadamente 1 milhão de registros com `a = 10`.
2. Existem aproximadamente 800 mil registros com `c = 15`.
3. Existem aproximadamente 2 mil registros com ambos.

Nesse último caso, se ele pegar qualquer um dos dois índices unicamente,
ainda teria muitas tuplas para pegar da tabela, para no final ficar com
apenas 2 mil registros. Então ele irá preferir navegar pelos dois
índices juntos, e pegar só o que interessa da tabela. Agora, como ele
faz isso? Da seguinte forma:

1. Navega no índice em (A,B) e busca pelos campos onde `a = 10`. Com o
resultado, gera um bitmap marcando as páginas que casam com 1 e que não
casam com 0
2. Navega no índice em (C) e busca pelos campos onde `c = 15` e gera um
bitmap desse resultado também.
3. Realiza uma operação de AND nos dois bitmaps, o que é bem rápido (são
só bitmaps) e gera como resultado um novo bitmap, que mapeia quais são
as páginas da tabela que contém ambos os valores.
4. Por fim, basta navegar nas páginas marcadas com o bitmap resultante
do AND anterior. Nesse caso ele terá que "reverificar" cada tupla de
cada página, mas veja que se a tabela tem 10 milhões e queremos apenas 2
mil registros, estamos falando de cerca de apenas 0,02% da tabela.

Vale ressaltar que o PostgreSQL usa dados estatísticos para encontrar
esses possíveis valores de retorno. Nesse caso ele não precisa da
quantidade **exata** de registros que cada filtro retorna, mas quanto
mais próximo do real, melhor serão os planos de execução criados. Logo,
manter as estatísticas atualizadas é uma tarefa muito importante.


Muito legal sua resposta Matheus, vc poderia transformar em post em seu blog hein!!!

Att,

--
   Fabrízio de Royes Mello         Timbira - http://www.timbira.com.br/
   PostgreSQL: Consultoria, Desenvolvimento, Suporte 24x7 e Treinamento
_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Responder a