Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Luiz Fernando7

Procedure que começa rápido e cai demais a performance

Recommended Posts

Ola a todos, Eu desenvolvi uma procedure que, basicamente pega os dados de uma tabela carregada pelo loader e insere os dados em uma outra. A diferença é que um mesmo registro dessa tabela pode gerar 1 ou 2 inserts na outra tabela com um campo alterado. Na tabela de origem tem aproximadamente 2 milhoes de registros, o que então pode gerar de 2 a 4 milhoes de registros na tabela de destino. A procedure começa muito rápida, processando pelo menos 10 mil registro por minuto. O problema é que a medida que o tempo vai passando ela vai diminuindo a performance inexplicavelmente e leva 30 horas pra rodar!!!! Se mantivesse o tempo de processamento era pra acabar em menos de 4 horas. Após 2 horas de processo essa velocidade de 10 mil/minuto já cai pra 5 mil/minuto e após algumas horas de processo para 500/minuto. Já tentei dropar todos os indices, foreign keys, checks, etc da tabela de destino e nada funciona. Como as tabelas são grandes não tem como inserir tudo de uma vez, senão eu destruo a tablespace temporária do banco. Então montei um loop que processa os dados de 5 em 5 mil: A lógica é: - Monta um cursor - Select /+*FIRST ROWS*/ (pega os primeiros 5 mil registros) - Insere na tabela destino - Se necessário insere novamente na tabela de destino com um flag alterado -> Fica nesse loop até processar os 2 milhoes de registros Alguém tem alguma idéia????? QUALQUER uma? hehehe Estou já bem atrasado no meu projeto e não consigo desagarrar disso. Muito obrigado, Luiz Fernando Heidenreich Reis

Compartilhar este post


Link para o post
Compartilhar em outros sites

cursor com milhões de registros... ainda mais com muitas informações (colunas)... ferra a memória... por isso essa perda de performance... você junta a memória do cursor com o segmento de rollback alocado no processo...

 

1 solução q não sei se vai ser útil... fazer um contador q dá commit a cada 10mil... mas o cursor ainda vai ferrar a memória... e você não tem garantia do processo retornar caso de algum pau no caminho...

 

2 solução seria usando um create table para este processo... pois o processamento fica muito mais eficiente.. algo do tipo...

 

CREATE TABLE xxxasSELECT *    FROM tabela_origem;INSERT INTO xxxSELECT campo1, campo2, campo3, campo4, CASE WHEN campo5 = 1 THEN 'SIM' ELSE 'NAO' ENDFROM tabela_origemWHERE campo1 = xyz;COMMIT;
bom... difícil de analisar sem conhecer as regras para essa duplicação... mas...

 

e de boa.. não sei qto eh grande o seu processo e os tratamentos dentro dele.. mas uma alteração em 15 milhões, em 4 horas é mais que suficiente!... só para você ter uma ideia... tive um serviço que eu tinha 2 tabelas... as 2 com 12milhões... todo o registro tinha um identificador sequencial único... e era minha chave para cruzamento....criei uma indice único ai:

1. estudei utilizar o UPDATE direto... e tinha muito risco se desse um ROLLBACK por algum motivo... iria demorar horas para o processo q iria impactar na perfomance...

2. fiz um cursor para agregar uma informação de uma tabela na outra... rodava q era uma beleza até cair no mesmo problema que você.. queda de performance... sobrecarga de memória, etc...

3. com o cursor ainda em uso, passei a usar o commit em blocos de 30.000 e usando o ROWID... melhorou.. mas não resolveu... problemas de performance tb

4. ultima solução foi um CREATE TABLE com um join das 2 tabelas e as regras direto na query.. case, decode, etc... o processo finalizou em 25 minutos... apesar de usar uma grande área da memória durante o cruzamento, mas nada comparado com o cursor!!!! e o melhor.. em 25 minutos...

 

 

;)

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.