Banco de Dados

23 abr, 2003

Firebird e seus PLANos de otimização

Publicidade

Se fossemos enumerar as qualidades
do Firebird, poderíamos citar : flexibilidade, simplicidade
e portabilidade.

No entanto, quando falamos de Servidores SQL, existem muitas outras
características que marcam sua excelência.
Por exemplo, um produto pode ser simples, flexível e portável,
mas e se a performance não for boa ?
Voce usuaria ele mesmo assim ?
Os que começam a usar o Firebird agora, ou começam
a trabalhar com Servidores SQL, normalmente ouviram falar que
os banco de dados SQL são os mais rápidos, mas saberia
responder do por que eles serem mais rápidos ?

Para quem usava ou ainda usa o Paradox, MS-Access
ou Dbase, a resposta à essa pergunta não é
fácil, pois estão acostumados ao modelo desktop,
onde normalmente a performance está diretamente ligada
à : performance do computador/servidor, performance da
rede, tamanho das tabelas e o uso de índices.

No modelo Cliente/Servidor a qual o Firebird se
encaixa, a resposta acima não está errada, porém
não é apenas isso que torna o Firebird tão
rápido. Parte dessa performance deve-se ao PLANO DE EXECUÇÃO
ou PLANO DE OTIMIZAÇÃO, vamos chamar esse recurso
de simplesmente PLAN.

Vamos entender um pouco, o que é o PLAN
?
PLAN é a forma que o Firebird usará (ou não)
os índices definidos no banco de dados na execução
de uma determinada querie com o intuito de fazer a recuperação
das informações a mais eficiente possível
(no menor tempo possível). Cada querie executada possui
um plano específico que pode ser definido automaticamente
pelo optimizador do Firebird ou manualmente pelo desenvolvedor
da aplicação.

Como ele faz isso ?

Por detrás de um servidor SQL (incluindo
o Firebird), existe um mecanismo chamado “Otimizador de Querie”,
isto é, quando voce submete ao servidor determinada querie,
esse “Otimizador” tem a tarefa de analisar sua querie,
seja ela simples ou complexa, avaliando : índices, combinações
de índices, agrupamentos como sort, union, (inner/outer/left)
joins, dentre muitas outras coisas, e depois de tudo analisado,
avalia o custo da operação.
Esse “custo da operação” é uma
especie de nota indicando se a otimização final
da querie foi boa ou ruim.
Se esse otimizador avaliar que o custo da operação
foi ruim, ele pode submeter a querie a outra otimização,
ou então não usar nenhuma otimização,
isto é o que chamamos de NATURAL PLAN.

No início pode parecer estranho a idéia
de não utilizar nenhuma otimização, mas lembre-se
de que em determinados casos, a melhor otimização
é realmente não usar nenhuma otimização,
muitas vezes re-avaliar uma operação ou selecionar
um índice pode levar mais tempo do que fazer uma varredura
numa tabela inteira, então nesse caso usar o “otimizador
de querie” não vai valer a pena.
Esse é o caso por exemplo de tabela pequenas ou então
de selects que não precisam de nenhum índice para
se efetuar uma busca.
Isto mesmo, pode ocorrer de uma tabela ter um campo indexado,
mas que o otimizador prefira não utiliza-lo.
Ficou nebuloso entender isso ?
Então vamos para um exemplo, suponhamos que voce possua
uma tabela de clientes chamada TABELA_CLIENTES, e suponhamos também
que exista um ÍNDICE (IDX_RAZAO_SOCIAL) para o campo de
“razão social”, se voce quiser pesquisar nesta
tabela todos os clientes que tenham a palavra “INDUSTRIA”
e “MOVEIS” não importa em que posição
no campo razao_social, como voce faria ? Certamente usaria o SELECT
da seguinte maneira :

SELECT * FROM TABELA_CLIENTES WHERE razao_social
LIKE ‘%INDUSTRIA%MOVEIS%’

Olhando o select a principio, poderíamos
determinar que a busca pelo indice “razao_social” seria
mais rápido, certo ?
Errado ! Porque o otimizador de querie utilizaria um índice,
se de qualquer forma ele terá de ver todos registros da
tabela para determinar a existencia das palavras “INDUSTRIA”
e “MOVEIS” ? Usar o otimizador de querie em sí,
já seria um completo disperdício e ter que selecionar
um índice para o caso acima seria tolice por parte do otimizador.
É para esses casos que existe o NATURAL PLAN.

Agora com o select modificado, fazendo busca por
clientes cuja razão social começem com a palavra
“INDUSTRIA” e contenham após “INDUSTRIA”
a palavra “MOVEIS” :

SELECT * FROM TABELA_CLIENTES WHERE razao_social
LIKE ‘INDUSTRIA%MOVEIS%’ (notem que não existe o “%”
no inicio do LIKE)

O otimizador de querie poderia determinar o uso
do índice criado para “razão social”,
pois no finito universo de dados, é possivel determinar
por ordem alfabética somente aqueles registros começando
com “INDUSTRIA” e que após isso possa conter
a outra palavra “MOVEIS”.
Seria uma busca muito mais rápida utilizando-se do índice.
Neste caso, não se usaria o NATURAL PLAN, pois certamente
o indice por razao_social seria adequado a pesquisa.

No exemplo acima, o otimizador de querie irá
analisar e determinará o melhor PLAN para a busca de clientes
cuja “razão social” começem por “INDÚSTRIA”
e depois contenha a palavra “MOVEIS”. Não é
preciso ser nenhum gênio para concluir que o otimizador
de querie preferirá usar o indice IDX_RAZAO_SOCIAL por
este se aplicar direitinho na pesquisa. Determinado o PLAN, então
a sua querie será modificada internamente pelo próprio
Firebird, que acrescentará a sua querie um parametro chamado
PLAN, ficando assim :
SELECT * FROM TABELA_CLIENTES WHERE razao_social LIKE ‘INDUSTRIA%MOVEIS%’
;
PLAN (TABELA_CLIENTES INDEX (IDX_RAZAO_SOCIAL))

Esse processo de submeter a querie para ser analisada
pelo “otimizador” para determinar um PLAN, é
chamado “Preparar”.
É por isso que programadores experientes, quando vão
executar uma querie parametrizada (aquela query que será
executada repetida várias vezes, porem mudando alguns parâmetros),
usam o método “Prepare/UnPrepare” antes de submeter
a querie ao banco de dados SQL, assim a querie não precisará
ser “otimizada” toda vez que for novamente submetida,
poupando recursos e melhorando a performance do servidor.

O Firebird permite que voce coloque em sua querie
um PLAN diretamente, assim o servidor seria “poupado”
de submeter sua querie a um otimizador de código. Isso
*teoricamente* deixaria seu servidor mais rápido.
Porque eu disse*teoricamente* ?
Porque em alguns casos, o PLAN que hoje é excelente pode
mudar conforme as condições de seu database vão
se modificando, por exemplo, voce pode acrescentar ao seu database
novos indíces, formulas, ou até mesmo o aumento
do volume de dados, tornando o PLAN anterior e fixo inadequado.

E um PLAN inadequado não é pior somente
para a sua querie, é ruim para todo o banco de dados, pois
queries concorrentes podem somar-se ao problema e transformar
o seu servidor em uma verdadeira tartaruga de 3 pernas.

Como testar os PLANos ?

Para voce entender como funcionam os PLANos no
Firebird, faça o seguinte :

1- Abra o IBConsole e conecte-se a seu banco de
dados ;

2- Crie uma query qualquer do tipo :
SELECT * FROM TABELA_CLIENTES WHERE razao_social LIKE ‘%INDUSTRIA%MOVEIS%’
(pegue qualquer tabela de cobaia);

3- Execute a querie ;

4- Selecione a orelha “Plan” (logo abaixo
de onde voce digitou a querie), veja :

Acrescentou-se a minha querie um tal PLAN (TABELA_CLIENTES
NATURAL), como eu havia dito antes, ou seja, o otimizador escolheu
não fazer nenhuma seleção de índice.

Para ver o tempo que essa query levou para ser
executada clique na orelha “Estatistics”:

Interessante, não ?
Levou nem 1 milisegundo para pesquisar em 7.091 registros, e se
tivesse usado qualquer outro indice teria demorado mais.

5- Vamos criar uma nova querie, dessa vez uma que
faça o Firebird usar o “otimizador de querie”.

Crie a seguinte querie :
SELECT * FROM TABELA_CLIENTES WHERE razao_social LIKE ‘INDUSTRIA%MOVEIS%’
Poderá usar qualquer outro campo, contando que tambem possua
um índice associado.
Execute a querie.

6- Selecione a orelha “Plan”, e observe que dessa vez
ele usou um PLAN :

Naturalmente, usou um PLAN que utilizasse um índice
associado a razão social.

E observe então as estatisticas :

Como essa tabela de clientes possui apenas 7.091
registros a performance não aumentou tanto assim, foi apenas
de 10% !
Mas a performance num ambiente cliente/servidor é linear,
isto quer dizer em outras palavras, que se o Firebird leva menos
de 1 segundo para encontrar um registro numa base com 10.000 registros,
a probabilidade de que com uma base 10 vezes maior, digamos 100.000
registros, o tempo nunca será de 10segundos, provavelmente
continuará a levar o mesmo 1 segundo.
Não é como nos bancos de dados desktop em que a
medida que aumentamos dez vezes nossos dados, perdemos uma performance
de 15 vezes ou mais.

Um dado interessante no Firebird é que essa
estatistica eu retirei num banco de dados em produção
e passados mais ou menos 15 minutos, fui até o Firebird
e re-executei a mesma querie anterior e note o seguinte :

A performance aumentou ainda mais, por que ?
Note que ele não fez nenhuma leitura, isto é, Reads=0,
isto quer dizer que quando o Firebird repete um PLAN já
executado anteriormente, ele vai buscar os dados em cache, e provavelmente
o tempo que levou para buscar os dados foi o tempo de transferencia
da memoria do servidor.
Em outras palavras, 00:00:00.0113 foi o tempo mínimo possivel
para executar o PLAN.
Aonde eu quero chegar ?

Vamos executar a mesma querie, porém mudemos
a clausula LIKE :
SELECT * FROM TABELA_CLIENTES WHERE razao_social LIKE ‘INDUSTRIA%’
(note que retiramos a palavra “MOVEIS”).
Com a modificação dessa dessa querie, um número
ainda maior de registros aparecerá e a performance diminuirá
em relação a execução anterior, certo
? Então executemos a querie acima e vejamos novamente as
estatísticas :

Note que ao invés da performance diminuir,
ela aumentou ?
Alguem poderia explicar o milagre, como é que eu aumento
a quantidade de registros numa seleção de querie
e a minha performance aumenta ao invés de diminuir ? Isso
tem a ver com a tal performance linear ?
A resposta a essa pergunta é : Veja a quantidade de leitura
física, notou ?
“Reads=0”, isto quer dizer que não houve leitura
física no disco. Provavelmente na execução
anterior, o Firebird trouxe muitos registros para a memória
além do que nós necessitavamos, em qualquer RDBMS
a leitura é por páginas e provavelmente todas as
páginas que satisfizeram a nova condição
LIKE já estava em cache e disponível para toda a
rede. Se outro usuário na rede precisasse de algum registro
já pesquisado por mim, usando o mesmo PLAN que eu, é
provavel que para esse usuário o Reads seria igual a zero
novamente.
Numa rede com muitos usuários simultanêos, essa performance
aumenta e vai muito além do que os outros banco de dados
desktop (dbf, access, paradox,…) poderiam nos dar.
Claro que isso não é linear a vida toda, como toda
a estatística matemática haverá um tempo
que essa curva linear tenderá a descer, e quando isso ocorrer
então já estará na hora de fazer um UPGRADE
no servidor

Considerações Finais

Percebeu como a “otimização
de query” e os “PLAN” são importantes ?
Agora voce iniciante no mundo SQL, poderá perceber o que
realmente faz diferença na performance num banco de dados
SQL Cliente/Servidor versus aplicações Desktop (Paradox,
Access, DBF,…).
É por causa de recursos como este que banco de dados como
Oracle, Sybase, MSSQL dentre outros custam tão caro.
No entato, agora voce tem os mesmos recursos usando o Firebird
que não lhe custa *nada*.