O documento fornece dicas sobre como otimizar bancos de dados, incluindo: (1) conhecer bem o projeto do banco de dados, (2) adotar boas práticas como documentação e nomenclatura padronizada, (3) otimizar consultas existentes utilizando explicações e tipos de dados corretos antes de refatorar, (4) observar pontos específicos como estrutura de consultas e uso de índices para otimizar.
16. ● Profissionais altamente capacitados para resolver os
problemas complexos, mas que deveriam ser simples.
LISTA DE EXIGÊNCIAS
● Tempo para executar uma implementação vai
aumentar por conta da complexidade.
● Aparição de gargalos técnicos no desenvolvimento de
soluções, pois as mesmas não foram PLANEJADAS
20. 1 2 3 4
CONHEÇA O
SEU PROJETO
ADOTE
BOAS PRÁTICAS
OTIMIZANDO O
NÃO OTIMIZADO
4 PASSOS PARA EXECUTAR UMA BOA OTIMIZAÇÃO
OBSERVE OS
PONTOS DE
OTIMIZAÇÕES
23. ● EXTERNA: O que os end-users veem
EX: Utilização de views para acesso de API's
PONTOS DE VISTA DO BD
● CONCEITUAL: Os objetos do BD em si
EX: Tipo de modelo de banco de dados: Flat, Relational, Dimensional, Graph,
Multivalue, Object-oriented, etc...
● FÍSICO: Organização do sistema de arquivo ou DBMS
EX: Tipo de storage engine: MyISAM, INNODB, XtraDB, etc
25. CONHEÇA SEUS REQUISITOS
• Evite deixar seu server de
banco de dados exposto
na internet
• Manter servers separados
dos ambientes de BD e
Aplicação
• Ter discos separados
para log, audit
• Ter estratégia de backup em
discos ou particionamentos
diferentes
• Preparar ambiente para
escalabilidade, horizontal
e/ou vertical
• Conheça bem suas
entidades no banco de
dados
• Trabalhe em conjunto
com a equipe (Requisito,
Arquiteto, GP,
Desenvolvimento)
HARDWARE SOFTWARE NEGÓCIO
H S N+ +
51. MANTENHA APÓS O REAL FUNCIONAMENTO DA
APLICAÇÃO, UMA MASSA DE DADOS PARA
DESENVOLVIMENTO (10% A 15%) DOS DADOS
REAIS, COM "MASCARAMENTO" DE ACORDO COM
O AMBIENTE
62. ANÁLISES PERTINENTES
• A(s) tabela(s) tem muitos registros?
• A consulta pode ter seu retorno de registro limitado?
• Existem joins na consulta?
• Os JOINS (INNER, LEFT, RIGHT,CROSS) estão sendo utilizados
corretamente?
• As operações de conjuntos (MINUS, INTERSECT, UNION) estão sendo
aplicadas corretamente?
• Na consulta existem filtros (WHERE / JOIN / ON)?
63. ANÁLISES PERTINENTES
• Na consulta existe agregação (GROUP BY / HAVING)?
• Na consulta existe ordenação (ORDER BY)?
• Os dados precisam ser ordenados?
• Os dados precisam ser agregados?
• Os dados precisam ser filtrados?
• Existe a possibilidade de paralelismo na consulta?
• Existe a possibilidade de particionamento da(s) tabela(s)?
• Existe a possibilidade de utilização de cache?
67. HORA DO EXPLAIN
EXPLAIN é utilizado para você ver como será feito o
plano de execução e a provável quantidade de dados
que determinada consulta vai trazer.
Ele é basicamente o banco de dados te "dando
satisfação" sobre o que e como vai fazer para retornar
seus registros pedidos através da sua query.
69. A PREVISÃO DO PLANO DE EXECUÇÃO
Os bancos de dados SGBD, normalmente coletam informações sobre
eles mesmos, gerando uma meta informação.
Ao guardarem os dados como: número de registros de uma tabela,
número de valores distintos, os valores que são mais comuns nessa
tabela, etc., ele faz cálculos e guarda as estatísticas para assim prever
sobre o que pode acontecer ao executar determinada “query“.
70. A PREVISÃO DO PLANO DE EXECUÇÃO
Uma coisa é preciso ter em mente: A forma que você faz a sua consulta,
é o que vai dizer se pode ser eficiente ou ruim para determinada
situação.
Os bancos de dados costumam ao fazer o plano de execução, examinar
todas as possibilidades possíveis, e leva em conta a quantidade linhas
que você quer selecionar, o critério (filtro), e geralmente, se bem
configurados, tomam as melhores decisões. (Mas, você pode forçar, caso
não queira ou concorde com o plano, que ele utilize manualmente as
rotas que preferir, como índices por exemplo).
73. Por mais óbvio (e incrível) que pareça, para você começar a
otimizar, você precisa entender a consulta e saber o que ela te
responde.
Para isso, algumas coisas são necessárias:
ESTRUTURA DA CONSULTA
74. ● FORMATAR A CONSULTA
● QUEBRAR A CONSULTA EM
CONSULTAS MENORES PARA
ENTENDER MELHOR O PROBLEMA.
● REESCREVER AS CONSULTAS
76. TIPOS DE DADOS
Os tipos de dados são parte importantíssima da otimização física. São
eles que definem o tamanho em bytes das colunas que compõem sua
tabela e, automaticamente, o tamanho das mesmas e seus respectivos
índices.
Além disso a conversão de dados quando não utilizados corretamente,
custam muito ao fazermos as operações do plano de consulta, como
vimos anteriormente.
78. ÍNDICES
Os índices são como sumários de um livro. Servem para te dar uma
referência de como achar determinado conteúdo/registro.
Saber identificar quais tipos de índices são melhores para cada tipo de
filtro é essencial para atingir o objetivo.
Não saia criando índices a deriva. Na construção do banco de dados, crie
apenas os índices que você tem CERTEZA que são necessários.
Uma dica útil no dia a dia é focar nos índices uniques.
79. ÍNDICES - QUANDO E ONDE UTILIZAR?
A utilização dos índices é um processo que auxilia e muito na
performance, desde que utilizados de maneira correta. A seguir seguem
alguns casos onde se faz necessário a utilização de índices
80. ÍNDICES - QUANDO E ONDE UTILIZAR?
WHERE, JOIN
Nesse caso as colunas que irão compor o índice serão as colunas que
compõe o WHERE ou JOIN. Por isso é importante manter os índices de
Chave primária e estrangeira, e de buscas comuns.
GROUP BY, ORDER BY
Nesse caso, os índices categorizam as colunas utilizadas, já que elas
separam e ordenam os valores das colunas indexadas, interrompendo o
"scan" assim que as possibilidades são finitas.
81. ÍNDICES - QUANDO E ONDE UTILIZAR?
DISTINCT
Nesse caso, muitas vezes, o DISTINCT tem um comportamento parecido
com o do GROUP BY, mas lava em conta também os índices contidos no
WHERE.
FUNÇÕES DE AGREGAÇÃO E RANGE
Para essas funções, o banco já sabe que vão procurar por determinados
valores, como no MIN(), OU MAX(). Quando essas funções são utilizadas
com particionamento de tabela, tem sua performance melhorada.
82. RECOMENDAÇÕES AO UTILIZAR OS ÍNDICES
Não é recomendado utilizar índices em campos em que a distinção de
dados da coluna seja muito pequena em relação ao número total de
registros. Ex: sexo, estado civil, raça-cor, campos de domínio em geral.
Isso é o que chamamos de "cardinalidade de coluna”
A criação dos índices devem seguir os requisitos descritos acima, se
não eles podem mais atrapalhar do que ajudar. Não se esqueça, os
índices ocupam espaço, às vezes maiores que as próprias tabelas.
84. TIPOS DE ÍNDICES
Existem vários tipos de índice e que funcionam
dependendo do SGBD. Alguns dos tipos padrões são:
85. TIPOS DE ÍNDICES
B-TREE
É o mais comum. São índices utilizados em consultas de
igualdade e de faixa, em dados que podem ser classificados.
Indicado para consultas com os operadores: <, <=, =, >=, >.
Também pode ser utilizado com LIKE, ILIKE, ~ e ~*. São
utilizados mais quando a cardinalidade da coluna é grande e
número de registros da tabela também é grande.
86. R-TREE
Esse tipo de índice é mais adequado a dados espaciais (latitude,
longitude). Adequado para consultas com os operadores: <<, &<, &>, >>,
@, ~=, &&.
HASH
Já os Hashes, são indicados para consultas com comparações de
igualdade simples. Praticamente não são utilizados mais. O ganho de
performance é praticamente nenhum em relação ao B-Tree.
TIPOS DE ÍNDICES
87. GIN/GIST
Utilizados para campos voltados para FTS ou JSON/BJSON, fazendo o uso
de dicionários para as consultas.
BITMAP
É um índice binário. utiliza-se de lógica booleana (AND/OR/NOT) para
ser construído. É melhor utilizado quando a cardinalidade de coluna é
pequena e o número de registros da tabela é grande. Por esse motivo,
esse tipo de índice é muito utilizado em modelos dimensionais, devido a
denormalização dos dados.
TIPOS DE ÍNDICES
89. Existe a possibilidade da consulta ser rodada em paralelo? Bancos como
PostgreSQL, Oracle, SQLServer possuem operadores no próprio comando
de "SELECT", que podem fazer isso, ou variáveis que "ligam" o modo.
Distribuir a consulta pelos processadores, podem trazer um ótimo
benefício, principalmente em processos de ETL/ELT (Extract Transform
Load / Extract Load Transform)
PARALELISMO
91. O particionamento de tabelas/índices é nada mais, nada menos que
dividir as mesmas fisicamente através de um critério. É recomendado
para objetos realmente grandes, > 1GB, por exemplo.
Podemos fazer esse particionamento de algumas formas:
PARTICIONAMENTO
92. RANGE
Neste método de particionamento utilizamos uma faixa de registros
obedecendo um determinado critério. Ex: Campos temporais.
LIST
Neste método de particionamento, utilizamos valores pré definidos para
particionar o objeto. EX: Campos de domínio e localização
PARTICIONAMENTO
93. HASH
Neste método de particionamento, utilizamos quando na tabela não
temos campos que definem blocos para serem particionados, mas
mesmo assim desejamos particionar. Logo, dessa forma não
conseguimos saber em qual partição se encontra determinado registro.
EX: Campos de chave primária e chave estrangeira.
PARTICIONAMENTO
94. COMPOSITE
Existe em alguns bancos a possibilidade de combinar os tipos de
particionamento, como Range-Hash e Range-List, formando assim
subpartições de um particionamento.
PARTICIONAMENTO
95. PARA UM USO EFICAZ DESSA METODOLOGIA, É PRECISO
ANTES TER UM CONHECIMENTO DO COMPORTAMENTO
OBJETO, COMO OS USUÁRIOS ATUAM EM CIMA DELE,
POIS CASO NÃO SEJA FEITA DE MANEIRA CORRETA, PODE
OCORRER O INVERSO, OU SEJA, PERDA DE
PERFORMANCE.
PARTICIONAMENTO
98. Quando pensamos num banco de dados relacional (RDBMS), estamos
pensando em ACID (acrônimo de Atomicidade, Consistência, Isolamento
e Durabilidade - do inglês: Atomicity, Consistency, Isolation, Durability).
Como esses bancos compartilham a mesma informação várias vezes
para usuários diferentes, o armazenamento em cache aumenta
eficiência de maneira bastante significativa.
CACHE
99. Imagine que 10000 usuários façam a mesma consulta. O cache alivia
para que o banco não tenha que processar a mesma coisa 10000,
processando apenas a primeira vez.
Logo o cache se faz extremamente importante no aumento e
performance quando o sistema tem uma grande ocorrência de
transações simultâneas e similares.
CACHE - EXEMPLO
100. QUERY RESULT CACHING
O cache de resultados de consulta, significa simplesmente que nós
guardamos na memória a saída exata de uma consulta SELECT para a
próxima vez que alguém execute essa mesma consulta SELECT.
TIPOS DE CACHE
101. QUERY PLAN CACHING
O cache de plano de consulta, envolve salvar os resultados do
"otimizador", que é responsável por descobrir exatamente "como" o
banco de dados vai buscar os dados solicitados. Uma vez que o caminho
para determinada consulta já é conhecido, não é preciso executá-lo
novamente, poupando assim processamento.
TIPOS DE CACHE
102. RELATIONAL CACHING
Esse tipo de cache de relação, consiste em basicamente guardar
geralmente uma tabela ou índice inteira para a memória de modo que
possa ser lido rapidamente. Isso economiza o acesso ao disco, ou seja,
economiza tempo. Esse tipo de cache é muito utilizado em sistemas
OLAP (Online analytical processing), encontrado nos modelos
dimensionais.
TIPOS DE CACHE
103. CACHE
Tente ativá-los e utilizar bastante deste recurso. Lembre-se que esse
recurso vai depender de Hardware, então, fique ciente que não adianta
ativar os caches, se o hardware não comportar!
TIPOS DE CACHE
105. OUTRAS OTIMIZAÇÕES
- Normalizar / Desnormalizar tabelas
- Recriar índices
- Clusterizar índices
- Eliminar objetos desnecessários no banco de dados
- Audite, logue com cuidado. (Selecione apenas o que deve ser logado)
- Quando mexer com modificações na tabela (UPDATE, INSERT, DELETE), tentar
fazer aos poucos, não tudo ao mesmo tempo.
- Prefira transações em lote (Uma instrução para vários registros) ao utilizar
(INSERT, UPDATE, DELETE)
- Materializar views
- Utilizar com cuidado a recursividade e cursores
107. TESTE, TESTE, TESTE
Faça testes condizentes antes de trocar as queries otimizadas pelas que já
funcionam. Saiba que quando você mexe no seu modelo, tudo é de alguma
forma impactado, então tenha uma análise de impacto dos objetos que foram
alterados
Tenha claro em sua cabeça que não existe "query mágica". Muitas vezes se
perde performance em um lugar para se ganhar em outro. Tenha de forma
gráfica as comparações de otimização de acordo com as consultas. Isso ajuda
a visualizar e perceber se a otimização é realmente utilizável.
110. UTILIZE VIEWS E MATERIALIZED VIEWS
As views podem ser utilizadas para dar a estrutura da
sua API, assim facilitando a manutenção da mesma. É
mais fácil de controlar as permissões de um determinado
conjunto de dados, principalmente se a mesma for
granular.
112. TOME CUIDADO COM OS ORM's
É uma mão na roda? É! Desenvolvedor AMA? AMA<3!
Mas muitas vezes os mesmos não selecionam os dados de maneira
performática, criando consultas redundantes e pífias pra seleções simples. O
importante aqui é SABER como e o que o ORM está selecionando, inserindo,
atualizando ou deletando na sua base e saber discernir se aquela "query" é
"boa".
Tome cuidado quando ao utilizar statements. De preferência ao fazê-las
explicitamente.
114. EVITE AO MÁXIMO O: SELECT * FROM TABELA
A instrução SELECT, serve justamente pra você
selecionar APENAS O QUE VOCÊ PRECISA.
Se você precisar de todos os campos, escreva o nome de
todas as colunas.
116. LIMITE A QUANTIDADE DE
REGISTROS DA SUA CONSULTA
Faz sentido trazer milhões de dados numa query?
As queries devem ter objetivos simples. Os operadores de
paginação como LIMIT E WINDOW devem ser usados
sem moderação, principalmente ao desenvolver.
118. EVITE USAR O "LIKE"
PARA BUSCAS TEXTUAIS
A utilização do LIKE degrada muito a performance.
Para buscas textuais complexas, existem outras formas
mais "bonitas" de se fazer, como o FTS (Full Text Search).
120. EVITE ESCREVER QUERIES
EXTREMAMENTE COMPLEXAS
Você pode utilizar functions e procedures para retornar como uma
tabela.
Isso traz segurança, e um pouco mais de liberdade e recursos
programáticos no banco de dados, evitando que a persistência ou
regras de negócio, dependam apenas da aplicação, principalmente
quando precisam ser persistidas.
122. • Não faz sentido ter um banco de dados relacional sem integridade
relacional, e elas são mantidas através de quem?
Ahhhh as CONSTRAINTS!
• Chave primária, SEMPRE NÚMERO! É muito mais rápido para
indexar e pesquisar do que texto.
NÃO FIQUE SEM UTILIZAR AS CONSTRAINTS
123. • CPF, CNPJ, ISBN, RG, NÃO SÃO chaves primárias. São apenas códigos padrões
únicos. A constraint para esses tipos de campo, é UNIQUE, não vá me colocar
CPF como chave primária, porque né, podemos ter mais de um CPF (SIM, EU
JURO)!
•
• As colunas que tipificam um dado, ou seja, são domínios, devem ter também
constraints, do tipo CHECK.
• Utilize as definições padrões das colunas do CREATE TABLE, como NOT NULL,
DEFAULT. Economiza a criação de constraints desnecessárias
NÃO FIQUE SEM UTILIZAR AS CONSTRAINTS
125. Isso pode ir contra a otimização em algum ponto, mas por outro lado,
mantém a integridade. Você pode utilizar as views para fazer os
cálculos ou constraints caso necessite mesmo do campo.
Entende-se como campo calculado, quando temos uma ou mais colunas
na mesma tabela que geram dado para uma nova.
Por exemplo: 3 colunas: a, b e c onde c = a+b
EVITE GUARDAR "CAMPOS CALCULADOS"
127. • Colunas do tipo BLOB são pesadas e custam muito espaço físico
em disco para tabela ou índice, afinal, é um campo binário
guardando normalmente arquivos.
• De preferência para guardar o link do arquivo no disco.
• Caso seja necessário, evite manter campos BLOBS em tabelas de
muita consulta.
• Crie uma tabela 1..1, mas não mantenha na mesma linha. Isso pode
te custar MUITA PERFORMANCE nas consultas.
SEPARE OS REGISTROS TIPO "BLOB"
129. Aprenda a utilizar corretamente os tipos nas colunas, afinal os todos
aqueles tipos existem para serem usados.
Todos eles tem sua particularidade e influenciam diretamente na
performance do banco, principalmente na questão de recurso físico,
como o tamanho de uma tabela e/ou índice.
UTILIZE CORRETAMENTE OS TIPOS DE DADOS