From: [email protected] Date: Mon, 10 Feb 2014 19:04:11 -0200 To: [email protected] Subject: Re: [pgbr-geral] Diferenças de performance rodando funcao
2014-02-07 12:57 GMT-02:00 Fabio Barros <[email protected]>: > > Boa tarde pessoal! > > Estou tentando entender a diferença de performance em duas implementações que > fazem a mesma coisa, mas ainda não consegui achar uma explicação. > > Segue abaixo os dois exemplos, caso alguém possa me ajudar no entendimento: > > Tenho um arquivo texto de 12 mil linhas, parte do conteudo abaixo: > > SELECT aux_ir_gao_generico ('I', 39700, '1621', '39700', 0); > SELECT aux_ir_gao_generico ('I', 39700, '1622', '39700', 0); > . . . > SELECT aux_ir_gao_generico ('I', 39700, '1623', '39700', 0); > SELECT aux_ir_gao_generico ('I', 39700, '1624', '39700', 0); > > ******* Fiz um programa C++ que simplesmente lê o arquivo e executa cada uma > de suas linhas, a seguir: > [...] > fseek (a_arq_executado, 0, SEEK_SET); > Não tem necessidade desse fseek aqui, mas acho que não faz mal também... > > for(int cont_linha = 1; (fgets(l_comando_sql, sizeof(l_comando_sql), > a_arq_executado) != NULL); cont_linha++){ > l_result = PQexec(l_conexao, l_comando_sql); -- comentando esta linha, > fica instantaneo (nao é problema ao ler o arquivo) > } > > [...] > > ******* No outro teste, fiz uma funcao postgres e 'embuti' as mesmas queries, > a seguir: > > CREATE FUNCTION insere_gao_mult () RETURNS INTEGER AS' > DECLARE > l_retorno INT; > BEGIN > > SELECT into l_retorno aux_ir_gao_generico (''I'', 39700, ''1621'', ''39700'', > 0); > SELECT into l_retorno aux_ir_gao_generico (''I'', 39700, ''1622'', ''39700'', > 0); > -- omitindo as outras linhas, só 12 mil dentro de uma funcao... rs > SELECT into l_retorno aux_ir_gao_generico (''I'', 39700, ''1623'', ''39700'', > 0); > SELECT into l_retorno aux_ir_gao_generico (''I'', 39700, ''1624'', ''39700'', > 0); > > [...] > Tempo do programa C++..................................: 1 minuto > Tempo executando a funcao q contem as linhas do arquivo: 3 segundos > > Particularmente, acho muito interessante este tipo de dúvida, e por isso > resolvi postar aqui.... > > Pq toda essa diferença no tempo?!?!?! (desculpem a ignorância) Bom, precisaríamos de uma análise mais detalhada para confirmar, mas o que percebi de mais imediato é o fato de você não trabalhar com transações no código em C, e uma função PL é sempre executada numa mesma transação, logo o tempo de início/fim de cada transação no código em C (basicamente a cada comando) pode pesar bastante. O mais equivalente seria: PQexec(l_conexao, "BEGIN;"); for(int cont_linha = 1; (fgets(l_comando_sql, sizeof(l_comando_sql), a_arq_executado) != NULL); cont_linha++){ l_result = PQexec(l_conexao, l_comando_sql); } PQexec(l_conexao, "COMMIT;"); Teste essa versão e nos diga o resultado. Ah, se for colocar isso em produção, não se esqueça de verificar por erros na execução de cada comando, ok? Mais uma coisa, a função em PL/pgSQL na primeira execução irá preparar os comandos e armazená-los em memória, assim uma execução subsequente será mais rápida, sem dúvidas, que a versão em C. Se o padrão do seu arquivo é sempre chamar a função aux_ir_gao_generico, há uma otimização bem simples, que é preparar a consulta: SELECT l_retorno aux_ir_gao_generico ($1, $2, $3, $4, $5); E depois executar passando os parâmetros. Atenciosamente,-- Matheus de Oliveira Analista de Banco de Dados Dextra Sistemas - MPS.Br nível F! www.dextra.com.br/postgres Perfeito Matheus!!! Fiz o teste com a transação e a diferença de tempo não existe mais, caiu do 1 minuto para 3 segundos, ou seja, meu gargalo estava justamente nisso e eu não me 'atentei' que repeti o processo 12 mil vezes. Obrigado pelas dicas, e quanto a verificar os erros de retorno, estou checando sim, só omiti do exemplo pra tentar deixar minha mensagem mais simples. Abraços a todos! Fabio Barros
_______________________________________________ pgbr-geral mailing list [email protected] https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
