[firebase-br] Performance Inclusão Massa x Trigger x Tabelas

Valdemir (gmail) valdemirjs em gmail.com
Sex Nov 30 16:23:34 -03 2012


Gladiston

Eu sempre nunca entendi bem mesmo como que os "caras do SQL", fazem magica, 
de deixar uma aplicação com um unico arquivo enorme, ficar mais rapida do 
que em arquivos pequenos separados por tabelas, sou da epoca do clipper e 
DBF.

Acredito que o firebird, deve fazer algum cache, quando uma trigger usa mais 
de uma tabela, eu na minha ignorancia, pensava que o fato de proteger um 
codigo em uma trigger não causaria lendição.. Ex

Supondo que seja necessario ferificar se o cliente tem saldo disponivel 
quando ele faz uma compra a prazo, para isso deve-se fazer uma consulta na 
tabela de clientes pelo campo LimiteDisponivel

na trigger before insert da tabela de vendas pensaria em fazer o seguinte

If valorPrazo > 0
    Select limitedisponivel from clientes where id = :parid into limite
    if ValorPrazo > limite
        Expception 'limite indisponivel'
    End
End

O codigo acima foi apenas para estudo provavelmente tem falhas ao compilar a 
trigger, mas enfim usando a logia acima, ele irá consultar a tabela de 
clientes apenas se o valorprazo > 0, ou seja na minha ignorancia de 
desenvolvedor, se o valor sempre for a vista, ele nunca passara pelo codigo, 
e teoricamente ele não vai causar queda de performance a não ser se a venda 
seja a prazo.

Mas pelo que eu vi, o firebird, verifica que na trigger carrega informação 
da tabela clientes, e ai acho que faz algum processo para deixar mas rapido 
a trigger se ele passar pelo codigo.

Este processo na vesão 2.5 será que esta mais inteligente ? , tipo ele 
verifica que o valor prazo não é maior que zero e ai nem perde tempo 
verificando o resto nem carregando em cache informações da tabela cliente ?

==============================================================================

Outra pergunta, quando vc fala em chamar uma SP, seria apos a inserção ? ou 
seja terei no script

Insert into clientes .....
Execute procedures SPVALIDA_CLIENTE

ou seja em 2 comandos para incluir o cliente ?

-----Mensagem Original----- 
From: Gladiston Santana
Sent: Friday, November 30, 2012 4:03 PM
To: FireBase
Subject: Re: [firebase-br]Performance Inclusão Massa x Trigger x Tabelas

Para fazer uma importação como a que você diz, deve-se desativar as
triggers e então fazer as inclusões que deseja. Se houver algum calculo
para fazer, executa-se isso no final da importação com os registros que
foram importados.
Triggers foram feitas para serem usados no momento de interatividade com o
programa/usuario, um bulkcopy com as triggers ativadas é penoso mesmo.
Outra coisa que se pode fazer é alterar seu sistema para que a
inclusão/alteração/exclusão chame uma SP que faça todas as operações
possiveis, nesse caso voce pode aproveitar a mesma SP no seu programa de
importação de dados, ao inves do insert, use execute procedure.


Gladiston Santana
Departamento de TI
Grupo Vidy
Tel (11) 4787-3122 ramal 228
Rod. Régis Bittencourt 3360 - Km 272,5
Taboão da Serra - SP - CEP: 06793-000
Visite nosso site: www.vidy.com.br
Visite também : www.expolabor.com.br





Em 30 de novembro de 2012 13:06, Valdemir (gmail)
<valdemirjs em gmail.com>escreveu:

> Boa tarde dia pessoal
>
> Aqui uso
> Delphi 2010 / IBO4 e Firebird 2.1
>
> Tenho as seguintes tabelas
>
> Pagamento Titualos
> Livro Caixa
> Cheques
> Banco
> MovCarcao
>
> Um pagamento de titulo, pode ser feito, atraves de cartão, ou atraves de
> deposito/boleto, ou ataves de dinheiro/cheque que ai entraria no caixa, e
> um cheque pode ser usado para pagamento mais de um titulo, e se o cheque
> voltar então aquele titulo fica “marcado” para o usuario saber de onde 
> veio
> aquele cheque
> Existe também a possibilidade de inclusão, ou alteração de valores, ou até
> mesmo um titulo que foi pago em banco, por um erro do usuario, pode na
> verdade foi pago em dinheiro, e ai no caso o usuario irá alterar o
> pagamento do titulo.
>
> Na trigger after insert x update x before delete, faço todas as
> checkagens, dou insert update ou delete nas tableas relacionadas, ou seja
> tudo na trigger da tabela “pagamento de titulos”. até ai ok, durante a
> digitação a performance é aceitavel o usuario não percebe lentidão.
>
> Agora estou montando uma importação em massa, leio o arquivo e gero um
> script INSERT INTO, e notei que o tempo para inclusão estava muito 
> lento...
> fiz alguns testes mudando a qtde de registros para dar commit, mesmo assim
> não tive um bom resultado
>
> Melhorei a performance da trigger, reescrevendo selects e inserts e
> updates para melhorar, também não foi o suficiente
>
> Ai então parti para a ignorancia .. rs, tenho um lote de 500 registros, o
> tempo para importalos com a trigger ligada leva em torno de 35/40 
> segundos,
> peguei a trigger e desliguei ela, o tempo caiu para menos de 1 segundo os
> mesmos 500 registros.
>
> Com isso descobri é pau na trigger, comentei a trigger inteira e fui
> descomentando ela aos poucos e constatei que realmente era problema na
> trigger.
>
> O que eu fiz, como na importação tenho todas as informações, não é
> necessário passar pela trigger, então fiz o seguinte, criei uma variavel 
> de
> contexto, e atribui um valor nela, e no inicio da trigger fiz o seguinte
>
> IF (UPPER(COALESCE(RDB$GET_CONTEXT('USER_SESSION','SINCRONIZANDO'),'NÃO'))
> = 'SIM') THEN
>   EXIT;
>
> Pensei agora vai ficar rapido, mandei rodar melhorou o tempo entre 22/27
> segundos, mas nada perto do que era antes, bom achei que era problema com 
> a
> minha variavem então peguei e coloquei um exit sem nenhum if e coloquei 
> uma
> msg de expetion para ter certeza que não estava passando pela trigger
>
>   EXIT;
>   exception except_geral 'teste';
>
> estas eram as duas primeiras linhas da trigger, o tempo não se alterou
> ficou entre 22/27 segundos, enfim tava ficando já meio careca com o
> problema, poruqe não passou pela trigger inteira, pq não deu o exception,
> mas mesmo assim o tempo continuou alto, ai então comentei todos os lugares
> de davam select, update insert ou delete em outras tabelas, e mandei
> rodar...
>
> Adivinhem o tempo caiu para incluir os 500 registros, menos de 400
> milesimos de segundo...
>
> achei o problema rs, testei desativando a trigger, e novamente o tempo foi
> otimo 392 milesimos de segundo para 500 registros, eu como desenvolvedor
> fiquei puto, afinal não esta passando pelo codigo não deveria demorar 
> tanto
> assim, bom fiz o seguinte, criei uma procedure para dar um insert update e
> delete, e ai tirei da trigger o insert update e delete, e chamei a função
> com o comando EXECUTE PROCEDURE, mesma coisa voltou para 22/27 segundos
>
> da a entender, que o otmizador do firebird, mesmo não usando o comando na
> determinada tabela, ele meio que carrega as tabelas dependentes da trigger
> e ai acaba deixando a trigger lenta mesmo se o codigo dela não for
> executado.
>
> É isso mesmo ?
> Este é um corportamento padrão do firebird ?, em versoes superiores o
> mesmo ocorre ?
> Existe como mudar isso com algum parametro ? semelhante quando fornecemos
> o plano para um select ?
>
> Eu para resolver simplesmente vou desativar as triggers como até já tinha
> visto sobre o assunto nas pesquisas que eu fiz, mas eu jurava que como já
> tinha feito uma condição para não passar na trigger quando estiver
> importando, não seria necessário desativar as triggers.
>
>
>
>
>
> ______________________________________________
> FireBase-BR (www.firebase.com.br) - Hospedado em www.locador.com.br
> Para saber como gerenciar/excluir seu cadastro na lista, use:
> http://www.firebase.com.br/fb/artigo.php?id=1107
> Para consultar mensagens antigas: http://firebase.com.br/pesquisa
______________________________________________
FireBase-BR (www.firebase.com.br) - Hospedado em www.locador.com.br
Para saber como gerenciar/excluir seu cadastro na lista, use: 
http://www.firebase.com.br/fb/artigo.php?id=1107
Para consultar mensagens antigas: http://firebase.com.br/pesquisa 





Mais detalhes sobre a lista de discussão lista