Durante este mês, passei alguns dias analisando um problema de performance que ocorreu em uma das rotinas de fechamento mensal da aplicação de um de meus clientes. O problema era o seguinte: durante a rotina, um dos programas executa uma série de INSERTS com SELECT FULL dos dados das tabelas origem para outras tabelas da aplicação. Isto é feito mensalmente desde (aguarde um minuto pois estou pegando o MIN de uma data da tabela ... hehehe) o mês 5/2006. Duas destas tabelas tem uma média de 2 milhões de registros/mês. Ou seja, após quase 4 anos, a tabela que armazena uma cópia mensal destes dados acumulou mais de 100 milhões de registros. Juntem a isso, mas 3 índices criados para acesso aos dados destas tabelas ... Como diria Milton Leite: que belezaaaa hein? ... Não é do nada que a performance dos INSERTs está horrível ...
Bem, deixando de lado esta indignação com o problema, vem a pergunta: Como otimizar estas operações sobre estas tabelas?
A primeira, e mais sensata idéia, porém a longo prazo, é questionar desenvolvedores e usuários sobre qual a utilidade destes dados e a real necessidade de serem armazenados integralmente todo o mês. Ainda, não podemos estipular uma política de backup e mantermos apenas os dados do último ano, por exemplo? Essas são algumas medidas que podem ser implementadas e que ajudarão a resolver o problema sem recorrer as features do Oracle para eliminar o problema de performance.
Caso os usuários demorem um pouco a responder, a solução mais rápida é partir para recursos do ORACLE que possam melhorar a performance.
Vamos a elas então ...
A primeira análise que fiz, foi verificar a configuração do parâmetro DB_FILE_MULTIBLOCK_READ_COUNT cuja influência no otimizador e nos tempos para executar FULL TABLE SCAN é muito grande. Este parâmetro, no meu caso, estava com configuração de valor 8 e imediatamente o modifiquei para 32. Vale lembrar que este parâmetro é dinâmico, então sua configuração já passa a ser utilizada para novas sessões no BD.
Feito isso, fui atrás de features que poderiam melhorar a performance dos INSERTS. Recorri, no manual Design And Tuning for Performance, à hint PARALLEL do Oracle. Seu uso paraleliza a operação de INSERT utilizando o número de server process desejado para execução do comando. No meu caso, utilizei o grau de paralelismo 8 coincidindo com o número de núcleos de processamento do servidor de banco de dados.
Exemplo do comando:
INSERT /*+ PARALLEL(my_target_table, 8) */ into my_target_table
(select * from my_source_table); Para a minha surpresa o comando que, antes levava 6h para concluir, passou a ser executado em 15min. Isso mesmo, 15min !!!!
Isso demonstra o poder e versatilidade das features do Oracle. A simples adição de uma HINT no comando pode trazer resultados fantásticos de performance !!!
Até a próxima.
bacana! bem legal
ResponderExcluirLegal o artigo.
ResponderExcluirEstou terminando minha Pós na FESP, só falta o TCC, vai ser sobre tuning.