[firebase-br] Queries (isql) úteis para verificação de métricas de banco de dados Firebird.
Alexandre Benson Smith
iblist em thorsoftware.com.br
Qui Dez 1 17:24:46 -03 2016
Em 1/12/2016 11:51, Alexandre Vinhaes - DBA - TIC escreveu:
> Bom dia senhores,
> alguém teria como disponibilizar um conjunto de queries básicas que eu
> possa executar via isql para verificação de problemas no banco Firebird ?
> Locks, contenções, utilização de memória, queries lentas, hit ratios etc ?
> Sou especialista em Oracle e SQL Server, porém estou começando com Firebird
> agora.
>
> Muito obrigado.
> Atenciosamente.
> Alexandre Vinhaes
Xará, não tenho as queries para tirar da manga...
Mas a principal causa de problema de performance no Firebird é o
controle transacional.
Abre-se a transação no inicio da aplicação e não a fecha (ou faz commit
retaining, que mantémo contexto transacional aberto). Por conta disso,
pelo fato do Firebird ser um banco que usa a arquitetura MGA (como o
Postgres e acho que o SQL Server tb se tornou em certo grau), vão
acumulando versões de registros, uma para cada visão do ambiente
transacional. em cada acesso o servidor precisa descobrir qual a versão
que aquela transação deve ver e com isso varre-se uma lista de versões,
algumas vezes bem grande. Segundo ponto é que como se acumula muito
"lixo", durante o processo de garbage collection, tem que se limpar
muito lixo.. Junta as duas coisas e a performance vai pro espaço.
Segundo ponto que mais identifico problemas é a falta de índices
adequados, mas aí não tem receita mágica.. tem que monitorar as queries
e ver qual é lenta e a partir daí otimiza-la (ou re-escrevendo ou o mais
comum, criando índices que faltam).. não tem receita mágica aqui.. cada
caso é um caso.
Um problema bem comum em queries lentas é algo neste sentido:
SELECT * FROM A LEFT JOIN B ON (A.A = B.A) WHERE B.B = 'XYZ'
O otimizador do firebird faz a análise combinacional dos "rivers" (para
simplificar, tabelas) até quando encontra um OUTER JOIN (seja ele LEFT
ou RIGHT). No exemplo acima, como só temos uma tabela antes do OUTER
JOIN, o otimizador é obrigado a começar por ela, e como não tem filtro
na clausula WHERE para a tabela A, não tem índice a ser usado apra
filtra-la, restando fazer uma leitura NATURAL desta tabela, e se ela for
grande, a performance vai pro espaço. Será usado indice no campo B.A e
B.B se tiver disponível, mas a tabela A será a primeira a ser lida e
será lida em sua totalidade.
Mas como otimizar está query então ?
Como o campo B.B está sendo testado com uma igualdade (e não faz
verificação de NULL), este LEFT JOIN é inútil, pois os registros não
encontrados na tabela B conterão obrigatoriamente NULL no campo B.B e
portanto serão excluídos do resultado final, basta trocar para um JOIN
comum e a performance mudará muito.
Um outro exemplo, similar, mas mais interessante para o mundo real.
SELECT
*
FROM
A LEFT JOIN
B ON (B.A = A.A) JOIN
C ON (C.A = A.A)
WHERE
C.C = 'XYZ'
O problema pro otimizador é o mesmo... ele para de fazer as permutações
de otimização entre as tabelas que estão até o primeiro OUTER JOIN,
neste caso, novamente só sobrou a tabela A, o filtro da cláusula WHERE
está na tabela C, supondo que em um campo com índice, mas pelo mesmo
motivo explicado acima, não será usado pelo filtro principal. Como
resolver este caso ? Simples.... Coloque todos os INNER's JOIN antes dos
OUTER's JOIN
SELECT
*
FROM
A JOIN
C ON (C.A = A.A) LEFT JOIN
B ON (B.A = A.A)
WHERE
C.C = 'XYZ'
Desta forma o otimizador poderá escolher entre começar a leitura pela
tabela A ou pela tabela C, como a tabela C tem um campo de filtro na
cláusula WHERE que tem um índice com boa seletividade, ele começará pela
tabela C e depois ira buscar a tabela A com base no índice do campo A.A,
provavelmente uma PK ou FK.
Uma mudança simples que melhora drasticamente a performance. Resumindo..
coloque sempre os OUTER JOIN's no fim (a direita se preferir) da query.
Fazer a otimização acaba por ser um problema simples de resolver (na
maioria dos casos), o grande problema é identificar o gargalo (que foi a
sua pergunta original). Embora eu não tenha as queries para tirar da
manga e te fornecer... Posso dar o caminho das pedras.
Estude as monitoring tables, lá tem uma série de informações úteis.
O utilitário GSTAT é seu amigo para dar informações sobre as
estatísticas do banco de dados, extremamente útil em muitos casos, mas
precisa aprender a ler seu resultado.
O fb_lock_print traz informações importantes sobre a tabela de lock do
Firebird, mas também, vai precisar saber o que procurar para poder
identificar e resolver o problema.
É difícil resumir em uma mensagem, que não seja um livro, os 3 temas
acima...
E fora o caminho das pedras.. tem o caminho da ponte.. que é ainda mais
simples... nem precisa molhar o pé e nem correr o risco de escorregar
nas pedras e cair no rio. Só que a ponte tem pedágio... :)
Olhe as ferramentas da IBSurgeon (IBAnalyst, Firebird Scanner, Firebird
MonLogger) elas fazem isso de forma automática, dão os resultados
mastigados e facilitam sua vida enormemente...
Veja:
https://www.youtube.com/watch?v=82cfMCkajU0&list=PL6tMVU1gu_R8aDsi9OBzo_YXRlydtXgcI&index=4
https://www.youtube.com/watch?v=C2L6YejILVc&list=PL6tMVU1gu_R8aDsi9OBzo_YXRlydtXgcI&index=3
https://www.youtube.com/watch?v=L5g3RmgjkiY&list=PL6tMVU1gu_R8aDsi9OBzo_YXRlydtXgcI&index=2
Ou o próprio HQBird, que é uma versão do Firebird com todas as
ferramentas incluídas e também outras funcionalidades.
até mais...
Mais detalhes sobre a lista de discussão lista