RES: [oracle_br] Re: melhorar performance insert
Verifique também, caso existam, quão pesadas são as triggers. As vezes a substituição das triggers por um processo separado de processamento destes dados ajuda bastante. -Mensagem original- De: oracle_br@yahoogrupos.com.br [mailto:[EMAIL PROTECTED] Em nome de jlchiappa Enviada em: segunda-feira, 29 de maio de 2006 15:55 Para: oracle_br@yahoogrupos.com.br Assunto: [oracle_br] Re: melhorar performance insert Rafael, não sei se vc recebeu a minha msg anterior sobre o tema, pra sua conveniência a repito ao final desta, ignore se vc já a recebeu. Vou fazer alguns comentários adicionais, vamos ver se te são úteis : a) vc não explica direito, mas pelo tom geral duduzo que o tal soft hoje busca a informação numa fonte de dados que não é um arquivo- texto, faz uma série de cálculos, inclusive rejeitando alguns registros, altera algumas colunas do registro lido e no final grava os regs aprovados, certo ? Em sendo isso, o uso do loader fica invalidado por não ser arquivo-texto. b) como eu disse, tabela em NOLOGGING só adianta de alguma coisa ** SE ** for usado direct-mode, e direct-mode IMPLICA que as condições que citei se cumprem, entre elas o insert não ser linha-a-linha c) antes de abandonar a opção de um único comando SQL, cheque as extensões mais recentes no dialeto SQL da Oracle, como CASE, cláusula WITH, funções analíticas, sub-query factoring, coisas que vc não conseguia fazer só em SQL ás vezes com os novos recursos dá d) se c) realmente não for possível de modo algum, vc vai partir pruma solução programada, o ponto ** PRINCIPAL ** aqui é que ler e gravar linha a linha é ** INAPELAVELMENTE ** lento, com a mais absoluta certeza eu diria que nesse caso nem parallel query nem storage nem coisa alguma (afora uma RE-ESCRITA do processo de modo a não fazer row by row) vai adiantar grande coisa. Essa re-escrita usaria algo MISTO, ie : procedural lendo a fonte de dados (** obviamente ** nunca lendo row by row, mas sim VÁRIOS registros por vez, armazenados num array), e OU é esse array que é gravado na tabela desejada (em BULK), OU cfrme o caso preenche-se uma tabela Global temporary table que depois é inserida em APPEND-MODE na tabela definitiva. Essa re-escrita até pode ser feita no próprio prog Java que vc tem hoje se for conexão jdbc com driver Oracle (que afaik aceita array processing e bulk collect), ** MAS ** recomendaria se pesar cuidadosamente a chance de se fazer em PL/SQL essa re-escrita, pois aí não só vc obtém array processing e bulk de modo transparente (ie, independente de driver), como também stored pl/sql tem as grandes vantagens que citei na minha msg. []s Chiappa --- Em oracle_br@yahoogrupos.com.br, "Rafael Mueller" <[EMAIL PROTECTED]> escreveu > > Agradeço pelas respostas, > > vamos lá, o uso do sql*loader ou insert into tabela (select dados...) não é > possível, o insert precisa ser realizado 1 por 1, pois a inserção é > resultado de um software que realiza calculos em cima de um modelo, e então > envia os resultados para o banco. > > A migração desse software para dentro do banco, é complicada pois é um > software bastante complexo e que usa muita memória (algo em torno de 200 mb > de memoria ram quando esta realizando os cálculos). > > Então as soluções que restaram é: > - Desabilitar os índices e depois recontruí-los. (talvez com NOVALIDATE) > - Colocar a tabela em NOLOGGING > - Parallel Query > - Modificações de storage. > > Algo mais pode ser modificado para melhorar a performance durante a > inserção? > > Seria possível fazer alguma procedure para auxiliar nessa inserção? > > Grato > > --- Em oracle_br@yahoogrupos.com.br, "jlchiappa" <[EMAIL PROTECTED]> escreveu > > Rafael, em primeiro lugar vc teria que ter feito o TUNNING do processo > que obtém os dados a inserir, se for um SELECT que ele esteja o mais > otimizado possível. > depois, no caso de append-mode, temos que notar que o hint de APPEND > só produz benefícios (gerando menos redo log) se : > > a) a tabela sendo inserida está em modo nologging > b) o banco NÃO está com o parâmetro de force logging ativado > c) o insert está sendo feito em "bulk", ie, MUITAS linhas de uma vez > INSERT /*+ APPEND */ INTO tabela (SELECTqueretornaummontãodelinhas); > > SE as condições acima não estão válidas, o APPEND que vc colocou não > serve de RIGOROSAMENTE nada na prática... E há ainda a questão de > manutenção de índices, NECESSARIAMENTE índices ativos durante uma > operação direct-mode serão SIM logados, se é uma operação de "carga", > considere a possibilidade de desabilitar os índices enquanto ela > ocorre , e depois os re-buildar em parallel nologging, se possível. Em > alguns casos, utilizar constraints deferred
[oracle_br] Re: melhorar performance insert
Rafael, não sei se vc recebeu a minha msg anterior sobre o tema, pra sua conveniência a repito ao final desta, ignore se vc já a recebeu. Vou fazer alguns comentários adicionais, vamos ver se te são úteis : a) vc não explica direito, mas pelo tom geral duduzo que o tal soft hoje busca a informação numa fonte de dados que não é um arquivo- texto, faz uma série de cálculos, inclusive rejeitando alguns registros, altera algumas colunas do registro lido e no final grava os regs aprovados, certo ? Em sendo isso, o uso do loader fica invalidado por não ser arquivo-texto. b) como eu disse, tabela em NOLOGGING só adianta de alguma coisa ** SE ** for usado direct-mode, e direct-mode IMPLICA que as condições que citei se cumprem, entre elas o insert não ser linha-a-linha c) antes de abandonar a opção de um único comando SQL, cheque as extensões mais recentes no dialeto SQL da Oracle, como CASE, cláusula WITH, funções analíticas, sub-query factoring, coisas que vc não conseguia fazer só em SQL ás vezes com os novos recursos dá d) se c) realmente não for possível de modo algum, vc vai partir pruma solução programada, o ponto ** PRINCIPAL ** aqui é que ler e gravar linha a linha é ** INAPELAVELMENTE ** lento, com a mais absoluta certeza eu diria que nesse caso nem parallel query nem storage nem coisa alguma (afora uma RE-ESCRITA do processo de modo a não fazer row by row) vai adiantar grande coisa. Essa re-escrita usaria algo MISTO, ie : procedural lendo a fonte de dados (** obviamente ** nunca lendo row by row, mas sim VÁRIOS registros por vez, armazenados num array), e OU é esse array que é gravado na tabela desejada (em BULK), OU cfrme o caso preenche-se uma tabela Global temporary table que depois é inserida em APPEND-MODE na tabela definitiva. Essa re-escrita até pode ser feita no próprio prog Java que vc tem hoje se for conexão jdbc com driver Oracle (que afaik aceita array processing e bulk collect), ** MAS ** recomendaria se pesar cuidadosamente a chance de se fazer em PL/SQL essa re-escrita, pois aí não só vc obtém array processing e bulk de modo transparente (ie, independente de driver), como também stored pl/sql tem as grandes vantagens que citei na minha msg. []s Chiappa --- Em oracle_br@yahoogrupos.com.br, "Rafael Mueller" <[EMAIL PROTECTED]> escreveu > > Agradeço pelas respostas, > > vamos lá, o uso do sql*loader ou insert into tabela (select dados...) não é > possível, o insert precisa ser realizado 1 por 1, pois a inserção é > resultado de um software que realiza calculos em cima de um modelo, e então > envia os resultados para o banco. > > A migração desse software para dentro do banco, é complicada pois é um > software bastante complexo e que usa muita memória (algo em torno de 200 mb > de memoria ram quando esta realizando os cálculos). > > Então as soluções que restaram é: > - Desabilitar os índices e depois recontruí-los. (talvez com NOVALIDATE) > - Colocar a tabela em NOLOGGING > - Parallel Query > - Modificações de storage. > > Algo mais pode ser modificado para melhorar a performance durante a > inserção? > > Seria possível fazer alguma procedure para auxiliar nessa inserção? > > Grato > > --- Em oracle_br@yahoogrupos.com.br, "jlchiappa" <[EMAIL PROTECTED]> escreveu > > Rafael, em primeiro lugar vc teria que ter feito o TUNNING do processo > que obtém os dados a inserir, se for um SELECT que ele esteja o mais > otimizado possível. > depois, no caso de append-mode, temos que notar que o hint de APPEND > só produz benefícios (gerando menos redo log) se : > > a) a tabela sendo inserida está em modo nologging > b) o banco NÃO está com o parâmetro de force logging ativado > c) o insert está sendo feito em "bulk", ie, MUITAS linhas de uma vez > INSERT /*+ APPEND */ INTO tabela (SELECTqueretornaummontãodelinhas); > > SE as condições acima não estão válidas, o APPEND que vc colocou não > serve de RIGOROSAMENTE nada na prática... E há ainda a questão de > manutenção de índices, NECESSARIAMENTE índices ativos durante uma > operação direct-mode serão SIM logados, se é uma operação de "carga", > considere a possibilidade de desabilitar os índices enquanto ela > ocorre , e depois os re-buildar em parallel nologging, se possível. Em > alguns casos, utilizar constraints deferred , ou mesmo , se vc tem > absoluta certeza que os dados já estão ok, um DISABLE e um ENABLE > NOVALIDATE nelas. > Afora isso, algumas recomendações adicionais : > > 1. se for uma carga extensa, e se houver a chance de se ter os dados > em arquivo-texto, o sql*loader ou external tables em nolog, parallel, > direct, etc, normalmente ** HUMILHAM ** outras soluções caseiras, com > loader nesses mesmos 11 minutos eu faço carga é de dezena de milhão de > linhas > > 2. se for exigida por qquer motivo solução programada, a PRIMEIRA > opção é SQL fazendo um único INSERT, construtos tipo : > > INSERT into
[oracle_br] Re: melhorar performance insert
Rafael, em primeiro lugar vc teria que ter feito o TUNNING do processo que obtém os dados a inserir, se for um SELECT que ele esteja o mais otimizado possível. depois, no caso de append-mode, temos que notar que o hint de APPEND só produz benefícios (gerando menos redo log) se : a) a tabela sendo inserida está em modo nologging b) o banco NÃO está com o parâmetro de force logging ativado c) o insert está sendo feito em "bulk", ie, MUITAS linhas de uma vez INSERT /*+ APPEND */ INTO tabela (SELECTqueretornaummontãodelinhas); SE as condições acima não estão válidas, o APPEND que vc colocou não serve de RIGOROSAMENTE nada na prática... E há ainda a questão de manutenção de índices, NECESSARIAMENTE índices ativos durante uma operação direct-mode serão SIM logados, se é uma operação de "carga", considere a possibilidade de desabilitar os índices enquanto ela ocorre , e depois os re-buildar em parallel nologging, se possível. Em alguns casos, utilizar constraints deferred , ou mesmo , se vc tem absoluta certeza que os dados já estão ok, um DISABLE e um ENABLE NOVALIDATE nelas. Afora isso, algumas recomendações adicionais : 1. se for uma carga extensa, e se houver a chance de se ter os dados em arquivo-texto, o sql*loader ou external tables em nolog, parallel, direct, etc, normalmente ** HUMILHAM ** outras soluções caseiras, com loader nesses mesmos 11 minutos eu faço carga é de dezena de milhão de linhas 2. se for exigida por qquer motivo solução programada, a PRIMEIRA opção é SQL fazendo um único INSERT, construtos tipo : INSERT into tabela (SELECTquemetrazoquequero) é MUITO mais performático do que código tipo slow-by-slow : loop obtém um registro; faço algum tratamento; insert no banco desse registro; saio se não há mais regs na fonte de dados; end loop; 3. se num único SQL não é possível por qquer motivo, considere FORTEMENTE a chance de usar PL/SQL armazenado no banco, pois nesse caso além de vc obter facilmente BULK COLLECT e ARRAY PROCESSING, vc ainda tem a GRANDE vantagem de que Pl/SQL reside no banco, os dados a consultar também, o tráfego de rede normalmente é MUITO minimizado com ele. ==> Estes pontos entendidos, avaliados e empregados, aí sim vc pensaria nosa itens mais avançados, como : eventuais modificações de storage para favorecer o INSERT (como FREELISTS/FREELIST GROUPS/PCT FREE/PCT USED), eventual uso de GTTs para se armazenar registros temporários, etc. []s Chiappa --- Em oracle_br@yahoogrupos.com.br, "Rafael Mueller" <[EMAIL PROTECTED]> escreveu > > Ola lista, > > tenho um software java que insere 800.000 linha em uma tabela, esse processo > demora 11 minutos. > > Gostaria de algumas dicas de como melhorar essa performance, já estou > utilizando o hint /*+ APPEND */ > > Grato, > > -- Rafael > > > [As partes desta mensagem que não continham texto foram removidas] > -- Atenção! As mensagens deste grupo são de acesso público e de inteira responsabilidade de seus remetentes. Acesse: http://www.mail-archive.com/oracle_br@yahoogrupos.com.br/ --__ Este Grupo recebe o apoio da SQL Magazine - www.devmedia.com.br/sqlmagazine __ O grupo Oracle_br não aceita anexos. Quando oferecer algum arquivo, tenha o link do mesmo para evitar trafego(pedidos) desnecessário. Yahoo! Grupos, um serviço oferecido por: PUBLICIDADE Links do Yahoo! Grupos Para visitar o site do seu grupo na web, acesse:http://br.groups.yahoo.com/group/oracle_br/ Para sair deste grupo, envie um e-mail para:[EMAIL PROTECTED] O uso que você faz do Yahoo! Grupos está sujeito aos Termos do Serviço do Yahoo!.