2013/12/6 Fabrízio de Royes Mello <[email protected]>

> 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!!!
>
>

kkkk... Acho que eu estava inspirado, =P.

Depois que eu mandei eu pensei exatamente nisso. Vou fazer logo que montar
um exemplo real também.

Valeu cara.

Abraços.

-- 
Matheus de Oliveira
Analista de Banco de Dados
Dextra Sistemas - MPS.Br nível F!
www.dextra.com.br/postgres
_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Responder a