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
