Conceitos principais do plano de execução de query: cost, rows, width
Quando você escreve uma query SQL, o PostgreSQL não sai executando logo de cara. Primeiro ele ativa o seu "cérebro" — o otimizador de queries, que monta o plano de execução. Esse plano é tipo um roteiro no mapa: o PostgreSQL calcula quais passos e em que ordem precisa fazer pra pegar os dados do jeito mais eficiente.
O otimizador de queries avalia todos os caminhos possíveis pra rodar sua query: varredura sequencial da tabela, uso de índices, filtragem, ordenação e por aí vai. Ele tenta achar o jeito mais barato (em termos de recursos) pra executar sua query. Ou seja, ele busca um equilíbrio entre tempo de execução e recursos do servidor.
Parâmetros chave do plano de execução
Beleza, agora vamos pra parte "hardcore" — destrinchar os parâmetros que o PostgreSQL mostra quando você roda o comando EXPLAIN. Pra começar, olha um exemplo simples:
EXPLAIN
SELECT * FROM students WHERE age > 20;
Você vai ver um resultado mais ou menos assim:
Seq Scan on students (cost=0.00..35.00 rows=7 width=72)
Filter: (age > 20)
Bora entender esses termos e números misteriosos.
1. cost (custo de execução)
cost — é uma estimativa de quanto recurso vai ser gasto pra rodar a query. Esse parâmetro tem duas partes:
- Startup Cost: custo pra começar a operação (tipo preparar o índice).
- Total Cost: custo total pra rodar tudo.
Exemplo:
cost=0.00..35.00
0.00— é o Startup Cost.35.00— é o Total Cost.
Quanto menor o cost, mais o PostgreSQL curte esse plano. Mas, importante: cost é um valor relativo. Não é em segundos ou milissegundos, é uma avaliação interna do PostgreSQL.
2. rows (quantidade estimada de linhas)
rows mostra quantas linhas o PostgreSQL acha que vai retornar ou processar nessa etapa da query. No nosso exemplo:
rows=7
Ou seja, o PostgreSQL acha que o filtro age > 20 vai retornar 7 linhas. Ele tira isso das estatísticas que coleta sobre a tabela. Se as estatísticas estiverem velhas, a previsão pode sair errada. Isso pode gerar um plano menos otimizado.
3. width (largura da linha em bytes)
width — é o tamanho médio de cada linha retornada nessa etapa, em bytes. No nosso exemplo:
width=72
Ou seja, cada linha retornada ocupa em média 72 bytes. width leva em conta o tamanho dos dados das colunas e uns overheads, tipo identificadores de linha ou info de sistema.
É tipo quando você baixa um app. Se ele for "pesado" (tipo o width alto), vai demorar mais pra baixar, mesmo se sua internet for rápida (tipo o cost).
Exemplo de análise de plano de execução
Bora ver um exemplo real. Imagina que temos a tabela students:
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
age INTEGER,
major VARCHAR(50)
);
E rodamos essa query:
EXPLAIN
SELECT * FROM students WHERE age > 20 AND major = 'CS';
O resultado pode ser assim:
Seq Scan on students (cost=0.00..42.50 rows=3 width=164)
Filter: ((age > 20) AND (major = 'CS'))
- Seq Scan: O PostgreSQL faz uma varredura sequencial na tabela
students. Ou seja, ele passa por cada linha. - cost=0.00..42.50: Custo da operação.
Startup Costé0.00, custo total é42.50. - rows=3: O PostgreSQL acha que o filtro
age > 20 AND major = 'CS'vai retornar 3 linhas. - width=164: Cada linha ocupa em média 164 bytes.
Agora você já saca como o PostgreSQL toma decisões e pode achar os gargalos nas queries. Por exemplo, se você vê um cost alto, pode ser que a query tá pesadona. Ou, se o rows tá trazendo muita linha, talvez vale revisar o filtro.
Como o cost funciona na prática?
Bora criar um índice na coluna age:
CREATE INDEX idx_age ON students(age);
Agora repete a query:
EXPLAIN
SELECT * FROM students WHERE age > 20 AND major = 'CS';
O resultado pode mudar:
Bitmap Heap Scan on students (cost=4.37..20.50 rows=3 width=164)
Recheck Cond: (age > 20)
Filter: (major = 'CS')
-> Bitmap Index Scan on idx_age (cost=0.00..4.37 rows=20 width=0)
Index Cond: (age > 20)
O que mudou?
- Em vez de
Seq Scan, agora éBitmap Heap Scan: o PostgreSQL primeiro acha as linhas certas no índiceidx_agee depois pega elas na tabela. - O
costcaiu bastante: agora oStartup Costé4.37e oTotal Costé20.50. - A operação ficou mais eficiente por causa do índice.
Visualização: diferença entre Seq Scan e Index Scan
Olha uma tabelinha comparando pra ficar mais claro:
| Operação | Introdução | Exemplo |
|---|---|---|
| Seq Scan | Lê a tabela toda | Passa por todas as linhas |
| Index Scan | Usa o índice | Pega as linhas rapidinho pelo índice |
Pegadinhas e erros comuns
Quando você usa os parâmetros do plano de execução, fica esperto com algumas surpresas. Por exemplo, nem sempre um cost baixo significa execução melhor. Se as estatísticas do banco estiverem velhas (tipo depois de atualizar muita coisa na tabela), o plano pode não ser tão preciso. Atualiza as estatísticas com o comando ANALYZE. Mais sobre isso na próxima aula.
Garante que você usa índices onde precisa. Mas não exagera: índice ocupa espaço e pode deixar as escritas mais lentas.
GO TO FULL VERSION