View
399
Download
4
Category
Preview:
DESCRIPTION
Apresentação sobre o "Query Planner" (planejador de consultas) do PostgreSQL
Citation preview
The PostgreSQL Query Planner
Por que minha consulta (SQL) precisa de um plano?
Simples...
● SQL é declarativo, ou seja, não é um programa
● Não possui controle de fluxo e não tem uma forma de controlar a ordem das operações– A não ser “While” e “For”, mas isso é conversa para
outro treinamento ;-)
● SQL pergunta O QUE, e não diz COMO
Planejador/Otimizador é o Cérebro do banco de dados...
… pois interpreta consultas SQL e
determina o método de execução mais
rápido.
Objetivos do Planejador
● Executar consultas mais rapidamente– Diminuir I/O de disco– Priorizar I/O sequencial a I/O randômico– Diminuir uso de CPU
● Não utilizar muita memória no processo
● Entregar resultados corretos
Decisões do planejador
● Método de Pesquisa (Scan Method)
● Método de Junção (Join Method)
● Ordem de Junção (Join Order)
Métodos de Pesquisa (Scan Methods)
● Sequential Scan● Bitmap Index Scan● Index Scan
Sequential Scan
DATA
DATA
DATA
DATA
DATA
DATA
DATA
DATA
DATA
DATA
DATA
DATA
8K
Heap
Sequential Scan
Bitmap Index Scan
0
1
0
1
AND =
0
1
1
0
0
1
0
0
801 AND 11
Index 1numcgm = 801
Index 2receit = 11
CombinedIndex
TABLE
Bitmap Index Scan
Bitmap Index Scan
Index 1k00_numcgm = 801
Index 2k00_receit = 11
Combined Index(And Operator)
Index Scankey
< = >
DATA
DATA
DATA
DATA
DATA
DATA
DATA
DATA
DATA
DATA
DATA
DATA
key
< = >
key
< = >
Index Scan
Index Scan
Dúvidas???
Tabela de exemplo
Função para EXPLAIN
Distribuição dos dados
Distribuição dos dados
tipo | count | % ------+-------+------ 5 | 14892 | 77.6 34 | 2714 | 14.1 14 | 575 | 3.0 6 | 555 | 2.9 25 | 384 | 2.0 13 | 70 | 0.4 1 | 3 | 0.0 32 | 1 | 0.0 27 | 1 | 0.0(9 rows)
Planos de execução
tipo | count | % | explain_arrecad ------+-------+------+------------------------------------------------------------------------------- 5 | 14892 | 77.6 | Bitmap Heap Scan on arrecad (cost=3.00..122.14 rows=96 width=52) 5 | 14892 | 77.6 | Recheck Cond: (k00_tipo = 5) 5 | 14892 | 77.6 | -> Bitmap Index Scan on arrecad_tipo_in (cost=0.00..2.97 rows=96 width=0) 5 | 14892 | 77.6 | Index Cond: (k00_tipo = 5) 34 | 2714 | 14.1 | Bitmap Heap Scan on arrecad (cost=3.00..122.14 rows=96 width=52) 34 | 2714 | 14.1 | Recheck Cond: (k00_tipo = 34) 34 | 2714 | 14.1 | -> Bitmap Index Scan on arrecad_tipo_in (cost=0.00..2.97 rows=96 width=0) 34 | 2714 | 14.1 | Index Cond: (k00_tipo = 34) 14 | 575 | 3.0 | Bitmap Heap Scan on arrecad (cost=3.00..122.14 rows=96 width=52) 14 | 575 | 3.0 | Recheck Cond: (k00_tipo = 14) 14 | 575 | 3.0 | -> Bitmap Index Scan on arrecad_tipo_in (cost=0.00..2.97 rows=96 width=0) 14 | 575 | 3.0 | Index Cond: (k00_tipo = 14) 6 | 555 | 2.9 | Bitmap Heap Scan on arrecad (cost=3.00..122.14 rows=96 width=52) 6 | 555 | 2.9 | Recheck Cond: (k00_tipo = 6) 6 | 555 | 2.9 | -> Bitmap Index Scan on arrecad_tipo_in (cost=0.00..2.97 rows=96 width=0) 6 | 555 | 2.9 | Index Cond: (k00_tipo = 6) 25 | 384 | 2.0 | Bitmap Heap Scan on arrecad (cost=3.00..122.14 rows=96 width=52) 25 | 384 | 2.0 | Recheck Cond: (k00_tipo = 25) 25 | 384 | 2.0 | -> Bitmap Index Scan on arrecad_tipo_in (cost=0.00..2.97 rows=96 width=0) 25 | 384 | 2.0 | Index Cond: (k00_tipo = 25) 13 | 70 | 0.4 | Bitmap Heap Scan on arrecad (cost=3.00..122.14 rows=96 width=52) 13 | 70 | 0.4 | Recheck Cond: (k00_tipo = 13) 13 | 70 | 0.4 | -> Bitmap Index Scan on arrecad_tipo_in (cost=0.00..2.97 rows=96 width=0) 13 | 70 | 0.4 | Index Cond: (k00_tipo = 13) 1 | 3 | 0.0 | Bitmap Heap Scan on arrecad (cost=3.00..122.14 rows=96 width=52) 1 | 3 | 0.0 | Recheck Cond: (k00_tipo = 1) 1 | 3 | 0.0 | -> Bitmap Index Scan on arrecad_tipo_in (cost=0.00..2.97 rows=96 width=0) 1 | 3 | 0.0 | Index Cond: (k00_tipo = 1) 27 | 1 | 0.0 | Bitmap Heap Scan on arrecad (cost=3.00..122.14 rows=96 width=52) 27 | 1 | 0.0 | Recheck Cond: (k00_tipo = 27) 27 | 1 | 0.0 | -> Bitmap Index Scan on arrecad_tipo_in (cost=0.00..2.97 rows=96 width=0) 27 | 1 | 0.0 | Index Cond: (k00_tipo = 27) 32 | 1 | 0.0 | Bitmap Heap Scan on arrecad (cost=3.00..122.14 rows=96 width=52) 32 | 1 | 0.0 | Recheck Cond: (k00_tipo = 32) 32 | 1 | 0.0 | -> Bitmap Index Scan on arrecad_tipo_in (cost=0.00..2.97 rows=96 width=0) 32 | 1 | 0.0 | Index Cond: (k00_tipo = 32)(36 rows)
Tá bom, só uma linha do EXPLAIN
Melhorou agora?
tipo | count | % | explain_arrecad ------+-------+------+------------------------------------------------------------------- 5 | 14892 | 77.6 | Bitmap Heap Scan on arrecad (cost=3.00..122.14 rows=96 width=52) 34 | 2714 | 14.1 | Bitmap Heap Scan on arrecad (cost=3.00..122.14 rows=96 width=52) 14 | 575 | 3.0 | Bitmap Heap Scan on arrecad (cost=3.00..122.14 rows=96 width=52) 6 | 555 | 2.9 | Bitmap Heap Scan on arrecad (cost=3.00..122.14 rows=96 width=52) 25 | 384 | 2.0 | Bitmap Heap Scan on arrecad (cost=3.00..122.14 rows=96 width=52) 13 | 70 | 0.4 | Bitmap Heap Scan on arrecad (cost=3.00..122.14 rows=96 width=52) 1 | 3 | 0.0 | Bitmap Heap Scan on arrecad (cost=3.00..122.14 rows=96 width=52) 27 | 1 | 0.0 | Bitmap Heap Scan on arrecad (cost=3.00..122.14 rows=96 width=52) 32 | 1 | 0.0 | Bitmap Heap Scan on arrecad (cost=3.00..122.14 rows=96 width=52)(9 rows)
Nada mudou né...
● Alguém arrisca dizer porque os planos estão iguais???
● Mesmo buscando qtds diferentes de dados da tabela???
Estatísticas desatualizadas
Estatísticas desatualizadas
ANALYZE é seu amigo...
Esses valores não são familiares???
Verificar planos de novo...
Interessante não?
tipo | count | % | explain_arrecad ------+-------+------+---------------------------------------------------------------------------------- 5 | 14892 | 77.6 | Seq Scan on arrecad (cost=0.00..499.94 rows=14892 width=52) 34 | 2714 | 14.1 | Bitmap Heap Scan on arrecad (cost=39.28..333.21 rows=2714 width=52) 14 | 575 | 3.0 | Bitmap Heap Scan on arrecad (cost=8.71..275.89 rows=575 width=52) 6 | 555 | 2.9 | Bitmap Heap Scan on arrecad (cost=8.55..275.49 rows=555 width=52) 25 | 384 | 2.0 | Bitmap Heap Scan on arrecad (cost=7.23..250.28 rows=384 width=52) 13 | 70 | 0.4 | Index Scan using arrecad_tipo_in on arrecad (cost=0.00..29.27 rows=19 width=52) 1 | 3 | 0.0 | Index Scan using arrecad_tipo_in on arrecad (cost=0.00..29.27 rows=19 width=52) 32 | 1 | 0.0 | Index Scan using arrecad_tipo_in on arrecad (cost=0.00..29.27 rows=19 width=52) 27 | 1 | 0.0 | Index Scan using arrecad_tipo_in on arrecad (cost=0.00..29.27 rows=19 width=52)(9 rows)
Vamos forçar um “IndexScan”?
Ficou mais rápido??
tipo | count | % | explain_arrecad ------+-------+------+-------------------------------------------------------------------------------------- 5 | 14892 | 77.6 | Index Scan using arrecad_tipo_in on arrecad (cost=0.00..779.24 rows=14892 width=52) 34 | 2714 | 14.1 | Index Scan using arrecad_tipo_in on arrecad (cost=0.00..434.27 rows=2714 width=52) 14 | 575 | 3.0 | Index Scan using arrecad_tipo_in on arrecad (cost=0.00..373.73 rows=575 width=52) 6 | 555 | 2.9 | Index Scan using arrecad_tipo_in on arrecad (cost=0.00..373.38 rows=555 width=52) 25 | 384 | 2.0 | Index Scan using arrecad_tipo_in on arrecad (cost=0.00..316.27 rows=384 width=52) 13 | 70 | 0.4 | Index Scan using arrecad_tipo_in on arrecad (cost=0.00..29.27 rows=19 width=52) 1 | 3 | 0.0 | Index Scan using arrecad_tipo_in on arrecad (cost=0.00..29.27 rows=19 width=52) 27 | 1 | 0.0 | Index Scan using arrecad_tipo_in on arrecad (cost=0.00..29.27 rows=19 width=52) 32 | 1 | 0.0 | Index Scan using arrecad_tipo_in on arrecad (cost=0.00..29.27 rows=19 width=52)(9 rows)
tipo | count | % | explain_arrecad ------+-------+------+---------------------------------------------------------------------------------- 5 | 14892 | 77.6 | Seq Scan on arrecad (cost=0.00..499.94 rows=14892 width=52) 34 | 2714 | 14.1 | Bitmap Heap Scan on arrecad (cost=39.28..333.21 rows=2714 width=52) 14 | 575 | 3.0 | Bitmap Heap Scan on arrecad (cost=8.71..275.89 rows=575 width=52) 6 | 555 | 2.9 | Bitmap Heap Scan on arrecad (cost=8.55..275.49 rows=555 width=52) 25 | 384 | 2.0 | Bitmap Heap Scan on arrecad (cost=7.23..250.28 rows=384 width=52) 13 | 70 | 0.4 | Index Scan using arrecad_tipo_in on arrecad (cost=0.00..29.27 rows=19 width=52) 1 | 3 | 0.0 | Index Scan using arrecad_tipo_in on arrecad (cost=0.00..29.27 rows=19 width=52) 32 | 1 | 0.0 | Index Scan using arrecad_tipo_in on arrecad (cost=0.00..29.27 rows=19 width=52) 27 | 1 | 0.0 | Index Scan using arrecad_tipo_in on arrecad (cost=0.00..29.27 rows=19 width=52)(9 rows)
DICA!
“Não tente ser mais esperto que o planejador.”
Mas ele não é “infalível”, se você já tentou de tudo e mesmo assim tem problemas, colabore seu plano conosco e nos
ajude a melhorá-lo:
pgsql-performance@postgresql.orgpgsql-hackers@postgresql.org
Métodos de Junção(Join Methods)
● Nested Loop– With inner Sequencial Scan
– With inner Index Scan
● Hash Join● Merge Join
Junção de duas tabelas com alta restrição (=)
Junção de duas tabelas com alta restrição (=)
Nested Loop(with Inner Sequencial Scan)
413
2134
5
27
6
Outer Inner
Nested Loop(with Inner Sequencial Scan)
413
2134
5
27
6
Outer Inner
Nested Loop(with Inner Sequencial Scan)
413
2134
5
27
6
Outer Inner
Nested Loop(with Inner Sequencial Scan)
413
2134
5
27
6
Outer Inner
Pseudocode for Nested Loop(with Inner Sequencial Scan)
Junção de duas tabelas com baixa restrição (>, <, <>)
Junção de duas tabelas com baixa restrição (>, <, <>)
Hash Join
413
2 1
34
5
2 7
6
Outer Inner
Deve caber na RAM
Hashed
Pseudocode for Hash Join
Junção de duas tabelassem restrição
Junção de duas tabelassem restrição
Merge Join
Outer Inner
Ideal para grandes tabelasUm índice pode ser usado para eliminar o “Sort”
234
1223
1
45
4
Sorted Sorted
Pseudocode for Merge Join
Algumas considerações
● Ordem das junções é insignificante● Outer Joins (left, right) podem afetar o
otimizador● Nested Loop pode usar índice na pesquisa● Restrições (where) afetam o uso de junções● LIMIT pode afetar o uso de junções
Dúvidas???
Recommended