Este comando mostra o plano de execução que o planejador do PostgreSQL gera para o comando fornecido. O plano de execução mostra como as tabelas referenciadas pelo comando são varridas — por uma varredura seqüencial simples, varredura pelo índice, etc. — e, se várias tabelas forem referenciadas, quais algoritmos de junção são utilizados para unir as linhas das tabelas de entrada.
Do que é mostrado, a parte mais importante é o custo estimado de execução do comando, que é a estimativa feita pelo planejador de quanto tempo demora para executar o comando (medido em unidades de acesso às páginas do disco). Na verdade, são mostrados dois números: o tempo inicial antes que a primeira linha possa ser retornada, e o tempo total para retornar todas as linhas. Para a maior parte dos comandos o tempo total é o que importa, mas em contextos como uma subseleção no EXISTS, o planejador escolhe o menor tempo inicial em vez do menor tempo total (porque o executor pára após ter obtido uma linha). Além disso, se for limitado o número de linhas retornadas usando a cláusula LIMIT, o planejador efetua uma interpolação apropriada entre estes custos para saber qual é realmente o plano de menor custo.
A opção ANALYZE faz o comando ser realmente executado, e não apenas planejado. O tempo total decorrido gasto em cada nó do plano (em milissegundos) e o número total de linhas realmente retornadas são adicionados ao que é mostrado. Esta opção é útil para ver se as estimativas do planejador estão próximas da realidade.
Importante: Deve-se ter em mente que o comando é realmente executado quando a opção ANALYZE é utilizada. Embora o comando EXPLAIN despreze qualquer saída produzida pelo SELECT, os outros efeitos colaterais do comando ocorrem da forma usual. Se for desejado utilizar EXPLAIN ANALYZE em um comando INSERT, UPDATE, DELETE ou EXECUTE sem afetar os dados, utilize o seguinte procedimento:
BEGIN; EXPLAIN ANALYZE ...; ROLLBACK;
Existe apenas documentação esparsa sobre o uso da informação do custo do otimizador no PostgreSQL. Veja a Seção 13.1 para obter mais informações.
Para que o planejador de comandos do PostgreSQL esteja razoavelmente informado para tomar decisões ao otimizar os comandos, o comando ANALYZE deve ser executado para registrar as estatísticas sobre a distribuição dos dados dentro da tabela. Se isto não tiver sido feito (ou se a distribuição estatística dos dados da tabela mudou de forma significativa desde a última vez que o comando ANALYZE foi executado), os custos estimados têm pouca chance de estarem em conformidade com as verdadeiras propriedades do comando e, conseqüentemente, pode ser escolhido um plano de comando inferior.
Antes do PostgreSQL 7.3, o plano era mostrado na forma de uma mensagem NOTICE. Agora aparece na forma do resultado de uma consulta (formatado como uma tabela de uma única coluna do tipo texto).
Mostrar o plano para uma consulta simples em uma tabela com uma única coluna integer e 10.000 linhas:
=> EXPLAIN SELECT * FROM foo; QUERY PLAN --------------------------------------------------------- Seq Scan on foo (cost=0.00..155.00 rows=10000 width=4) (1 linha)
Havendo um índice, e sendo feita uma consulta com uma condição WHERE indexável, o comando EXPLAIN pode mostrar um plano diferente:
=> EXPLAIN SELECT * FROM foo WHERE i = 4; QUERY PLAN -------------------------------------------------------------- Index Scan using fi on foo (cost=0.00..5.98 rows=1 width=4) Index Cond: (i = 4) (2 linhas)
O exemplo abaixo mostra o plano para uma consulta contendo uma função de agregação:
=> EXPLAIN SELECT sum(i) FROM foo WHERE i < 10; QUERY PLAN --------------------------------------------------------------------- Aggregate (cost=23.93..23.93 rows=1 width=4) -> Index Scan using fi on foo (cost=0.00..23.92 rows=6 width=4) Index Cond: (i < 10) (3 linhas)
Abaixo está um exemplo da utilização do comando EXPLAIN EXECUTE para mostrar o plano para uma consulta preparada:
=> PREPARE query(int, int) AS SELECT sum(bar) FROM test -> WHERE id > $1 AND id < $2 -> GROUP BY foo; => EXPLAIN ANALYZE EXECUTE query(100, 200); QUERY PLAN ------------------------------------------------------------------------------------------------------------------------- HashAggregate (cost=39.53..39.53 rows=1 width=8) (actual time=0.661..0.672 rows=7 loops=1) -> Index Scan using test_pkey on test (cost=0.00..32.97 rows=1311 width=8) (actual time=0.050..0.395 rows=99 loops=1) Index Cond: ((id > $1) AND (id < $2)) Total runtime: 0.851 ms (4 linhas)
Obviamente, os números específicos mostrados aqui dependem do conteúdo real das tabelas envolvidas. Deve ser observado, também, que os números, e mesmo a estratégia selecionada para o comando, podem variar entre versões diferentes do PostgreSQL devido a melhorias no planejador. Além disso, o comando ANALYZE utiliza amostragem aleatória para estimar as estatísticas dos dados; portanto, é possível que as estimativas de custo mudem após a execução do comando ANALYZE, mesmo que a distribuição real dos dados da tabela não tenha mudado.