[oracle_br] Re: Delete de Milhões de linhas

2015-07-27 Por tôpico alexssandro0...@yahoo.com.br [oracle_br]
Bom dia! 

 Chiappa, obrigado pela sua ajuda, com as tuas colocações, irei fazer uma 
rotina que realiza o bulk delete de 10.000 registros por execução, diminuindo 
ao máximo a carga no servidor, pois não tenho como fazer isso sem impacto no 
servidor e vou utilizar o parallel de pobre, para que eu possar executar mais 
de um processo ao mesmo tempo. 
 

 Fazer estes deletes com insert /*APPEND*/ into, não é a melhor opção para o 
meu ambiente.
 

 Referente a o EXCEPTION WHEN OTHERS eu irei retirar, pois como você colocou, 
não tenho controle sobre os erros. e não saberei que problema está acontecendo.
 

  
 

   
 

 



[oracle_br] Re: Delete de Milhões de linhas

2015-07-27 Por tôpico jlchia...@yahoo.com.br [oracle_br]
Opa, algumas obs finais, mais para referência de quem for ler a thread :

 a. via de regra um dos grandes overheads da Deleção de registros é que é 
Inescapável o fato de se gerar UNDO e um REDO : isso decorre dos ditames da 
teoria de bancos de dados relacionais, que DEMANDA que TODA e QUALQUER operação 
seja reversível/passível de ser cancelada (daí o UNDO) ** e ** que também seja 
Recuperável (daí o REDO, que vai ser usado para recuperar os datafiles em caso 
de crash) A maneira ** única ** de remover dados gerando o mínimo possível 
de UNDO e REDO (quase zero, mas não é zero por causa das tabelas internas do 
RDBMS) seria mesmo, depois de se ter salvo numa outra tabela os registros que 
se quer preservar, se fazer o ** TRUNCATE ** da tabela, que a esvazia de uma 
vez e não é uma Operação reversível, portanto não precisa gerar redo/undo para 
todos os dados da tabela, E só então se carregar de volta os dados a serem 
mantidos, preferencialmente com INSERT /+ APPEND */ para que a Inserção em si 
gere também o mínimo de redo (UNDO naturalmente quase não é gerado por um 
INSERT, pois Obviamente para se desfazer um INSERT é só 'zerar' a informação 
que está in place)...
 O que quero que fique ** CLARO ** aqui é que quem está poupando recursos aqui 
é o *** TRUNCATE **, e não o INSERT /* APPEND */, ok ??? Claro que o INSERT /*+ 
APPEND */ poderia ajudar bastante no processo de gerar uma tabela-cópia com 
os dados a serem mantidos, e que Ajudaria Muito também na hora de inserir os 
dados de volta depois do TRUNCATE, mas se não fosse possível o APPEND-mode por 
qquer motivo, até se poderia fazer a salva dos dados e a carga de volta após o 
TRUNCATE com INSERTs normais , export+import, sql*loader ou o que fosse
 
 NO SEU CASO, entendo que o que está te impedindo é a impossibilidade de janela 
de manutenção permitindo o acesso exclusivo requerido pelo TRUNCATE e pela 
salva/carga de dados antes e depois dele, e não o APPEND em si, ok 
 
 b. provavelmente vc não deve ter os recursos para tal, mas que fique 
REGISTRADO que via de regra se ter as múltiplas sessões paralelas fazendo um 
DELETE direto nos ROWIDs necessários, SEM cursor, é mais performático do que o 
fazer dentro de cursor , seja com ou sem bulk processing 
 No seu caso, estou Assumindo que isso não será possível por causa de não ter 
espaço suficiente para crescer a área de ROLLBACK/UNDO para poder conter todo o 
undo gerado pelo DELETE, então por isso vc vai fazer um LOOP , ie, para poder 
comitar de tantos em tantos mils registros : isso implica em OVERHEAD, já que 
cada COMMIT implica em checkpoint, término de transação e consequente flush de 
redo, mas se vc não tem o necessário para a opção de maior performance, então 
não tem, que sseja assim...

 c. os limites específicos (ie, quantas sessões simultâneas vc vai ter, qual 
será o LIMIT para o seu array pro BULK COLLECT e pro FORALL, etc) vai ser 
determinado pelo seu ambiente , mas eu diria pra vc TESTAR, numa 
máquina/ambiente/hardware o mais parecidos possíveis com a sua prod, a 
possibilidade de umas três sessões simultâneas , LIMIT de 1000 ou 2000 e COMMIT 
a cada 100 mil registros - esses números são baixos, são números que são 
razoáveis para a maioria dos servidores de produção que tenho visto, são os 
mais prováveis de não dar probs Aos poucos vc pode testar a chance de 
Ligeiros e paulatinos aumentos : não queira logo de cara sair jogando lá em 
cima esses números que quanto mais vc sobe mais alta a chance de vc esbarrar 
nos limites, seja do hardware, do ambiente OU mesmo do PL/SQL em si, como eu 
disse numa thread recente
 
  d. no instante em que vc bypassa o processamento normal e faz DML via 
cursor de usuário, é vc que fica responsável pelo tratamento de erros : assim, 
não deixe de pesquisar e incluir na sua rotina uma cláusula SAVE EXCEPTION no 
FORALL que vai montar o array com os ROWIDs a se deletar, para que nos 
registros que der erro/conflito por causa de contraint/whatever vc não perca a 
rastreabilidade deles - por mais que a gente verifique e verifique, sempre 
acaba passando algum...  
https://heliodias.wordpress.com/2010/01/07/best-way-to-delete-millions-rows-from-hundred-millions-table/
 tem uns exemplinhos e discussão geral , e também se vc pesquisar em 
http://asktom.oracle.com vc acha boas refs
  
  e. o MAIS IMPORTANTE para a performance : além de usar corretamente o 
processamento por array/bulk, é FUNDAMENTAL que a query do cursor principal, 
que busca os registros a se deletar, esteja Absolutamente Otimizada - veja 
Direitinho quais índices vc tem para ter a melhor condição de filtro se for o 
caso, veja (já que afaik vc terá uma tabela com os registros a preservar) se é 
interessante ao invés de se fazer um JOIN da tabela com dados a preservar com a 
tabela real vc ao invés fazer um ANTIJOIN ou um semijoin (vide 
http://www.dbspecialists.com/files/presentations/semijoins.html) 
  
  f. como eu disse em msgs anteriores, vc VAI jogar no