Opa, boa tarde!
Segue um bloco de exemplo.
CREATE TABLE teste_update (ID NUMBER, texto CHAR(1))/SELECT * FROM
teste_update/SQL> desc teste_update;Name Type Nullable Default Comments
- --- --- ID NUMBER Y
TEXTO CHAR(1) Y
SQL>
DECLARE
CURSOR C IS SELECT ROWID rrowid FROM teste_update; -- se tiver
um filtro de data vc pode rodar em parallel
TYPE T_C IS TABLE OF C%ROWTYPE;
C_Array T_C;
BEGIN
dbms_application_info.set_action('Abrindo cursor'); OPEN C; -- LOOP
dbms_application_info.set_action('Qtd C '||C%ROWCOUNT); FETCH C BULK
COLLECT INTO C_array LIMIT 1;
FORALL i IN 1..C_array.count UPDATE teste_update SET texto =
'.' WHERE rowid = C_Array(i).rrowid;
COMMIT;
EXIT WHEN C%NOTFOUND;
END LOOP;
COMMIT;
CLOSE C;
EXCEPTION WHEN OTHERS THEN ROLLBACK; RAISE;
END;/-- vc pode criar uma procedure com parametro de entrada no bloco acima e
depois usar esse bloco abaixo para atualizar em parallel
DECLARE
L_date DATE := DATE '2013-03-14'; L_date_f DATE := DATE '2013-03-15';
BEGIN -- FOR i IN REVERSE 0..(L_date_f-L_date)-1 LOOP --
dbms_application_info.set_module('BKLOG', TO_CHAR(L_date + i, '-mm-dd'));
-- BEGIN -- NULL; -- END; -- END LOOP; --END;
Espero que ajude.
Abs,
Em Terça-feira, 17 de Outubro de 2017 14:48, "Ricardo Sá
ricardo@terra.com.br [oracle_br]" escreveu:
Chiappa, De fato foi o que aconteceu, inicialmente o bloco PL/SQL rodou
tranquilo, a cada 100.000 linhas, porém aos poucos foi ficando lento, aí eu
cancelei.E fiz exatamente o procedimento que você informou neste, ou seja,
dropei todos os índices, desabilitei as triggers, em um base StandBy em um DG
que mantenho.Estabeleci uma área de UNDO de 256GB de disco e RETENÇÃO de 6
Horas.O processo rodou em 2 horas, em um servidor com recursos inferior ao de
produção ( 2 Nodes rodando em storage VNX bem configurado pelo pessoal da
DELL-EMC).Depois a recriação dos índices demorou 1 hora rodando com parallel
10, totalizando todo o processo aprox.. 3 horas.Irei rodar este processo em uma
janela bem folgada no amb produção , e acredito que irá cair para quase a
metade do tempo. De qq forma, muito obrigado pela abordagem. Att.:Ricardo
De: oracle_br@yahoogrupos.com.br [mailto:oracle_br@yahoogrupos.com.br]
Enviada em: terça-feira, 17 de outubro de 2017 13:55
Para: oracle_br@yahoogrupos.com.br
Assunto: Re: RES: [oracle_br] AJUDA - UPDATE MONSTRO TABELA DE 11,5 MILHOES DE
LINHAS Ricardo, eu ** discordo ** dessa Abordagem : se o objetivo é máxima
Performance o correto e Recomendado é vc ter uma área de ROLLBACK o mais larga
Possível e fazer num comando só INCLUSIVE, eu imagino que vc Saiba que :
a. cada COMMIT *** implica *** em espera por I/O, já que força um sync write
b. vc está jogando PELA JANELA a integridade dos dados, pois se vc tinha que
processar x linhas, processou menos que isso e deu um COMMIT, se as próximas
linhas falharem vc acabou com uma tabela MEio processada e Meio não processada,
comofaz ??
c. vc está jogando PELA JANELA o conceito de Transação, que demanda que ***
TODOS *** os comandos/operações Tem que ser reversíveis : ora , no mesmo
exemplo de cima se vc comitou algumas vezes no LOOP e depois disso houve falha
(ou o usuário quer Desfazer a transação) o ROLLBACK SIMPLESMENTE NÃO VAI
FUNCIONAR, o que tá comitado comitou, comofaz??
==> NADA do que eu disse é novidade, há 15 anos o Tom Kyte já falava isso, vide
https://asktom.oracle.com/pls/asktom/f?p=100:11:0P11_QUESTION_ID:4951966319022
. PENSE NESSAS CONSEQUÊNCIAS antes de sair usando essa 'técnica', sim sim
???
imho os procedimentos Performáticos e Seguros de se fazer seriam :
1. Paralelismo : já que é EE vc ** necessariamente ** TEM aí na mão a chance
de rodar o DML em parallel-mode e/ou de ler os registros que quer alterar em
Parallel... O degree de parallelismo vai depender muito do teu hardware, vc tem
que levantar qual tua capacidade em termos de CPU e I/O...
ou
2. se a Maioria das linhas vão ser Updateadas, vc faz um INSERT */ APPEND */
num outra tabela , alterando o valor que quer alterar : isso vai diminuir
MONSTRUOSAMENTE o tanto de redo log gerado (não vai zerar mas vai Diminuir
Enormemente!!) e é mais rápido que UPDATE, veja
https://asktom.oracle.com/pls/apex/asktom.search?tag=how-to-update-millions-or-records-in-a-table-200211#6417104879869
para um Exemplo
===> E NECESSARIAMENTE um DML largo é SIM uma Manutenção da tabela, então TEM
que ser feita num período de menor carga no sistema, e PREFERENCIALMENTE, com
os índices E constraints desabilitados, os quais vc Reconstruiria em parallel
depois e com NOVALIDATE nas constraint se possível...
[]s
Chiappa
OBS : se por qualquer Motivo não puder fazer Parallel SQL ao menos valide a
opção de B