Só pra a adicionar... Este livro do Tom Kyte vai sair nova edição, adicionando características do 11g.
http://www.amazon.com/Expert-Oracle-Database-Architecture-Programming/dp/143 0229462/ref=pd_sim_b_13 Até mais, _____ De: oracle_br@yahoogrupos.com.br [mailto:oracle...@yahoogrupos.com.br] Em nome de José Laurindo Enviada em: quarta-feira, 14 de julho de 2010 09:48 Para: oracle_br@yahoogrupos.com.br Assunto: [oracle_br] Re: UPDATE em milhoes de registros Bom, a gente responde, o forum server pra isso, mas ** FATALMENTE ** vc vai precisar de um update aí no seu conhecimento pra poder atuar como DBA, não dá pra ira até os detalhes necessários de implementação aqui no fórum, nem é a proposta... Bom, no caso dos índices o que ocorre é que , se vc os desativar durante o DML que não precisa dele (ie, DNL que atuará na tabela toda e portanto terá mesmo que fazer um full table scan) , após o DML vc pode pedir pro banco o reconstruir gerando um múnimo apenas de redo log, é o chamado modo NOLOGGING, veja os detalhes na doc Oracle, em especial no manual "Oracle® Database Administrator's Guide" no cap. 16 Managing Indexes. Claro, é o ** TESTE ** no seu ambiente que vai indicar se essa técnica é proveitosa ou não, muitas vezes é, mas cada caso é um caso... E lógico : - há RESTRIÇÕES para isso, como (entre outras) se o DML está ocorrendo isoladamente, numa janela de manutenção, ou não - há IMPLICAÇÕES na hora de se fazer recuperação dum objeto criado assim, o DBA ** TEM ** que entendê-las Precisamente Sobre o parelelismo, isso é um conceito bem comum no bd Oracle para bancos não-oltp, consiste em (para operações LONGAS, que vão atuar em milhares de blocos, o que parece ser o seu caso) pedir para o banco abrir várias "threads", vários Processos simultâneos, cada um lendo um 'pedaço' da tabela a trabalhar : via de regra, SE o hardware tem capacidade ociosa, é MUITÍSSIMO mais eficiente se ter n processos no banco trabalhando juntos cada um num pedaço do todo do que se ter apenas um, que enquanto está lendo nâo atualiza e enquanto atualiza não está lendo... Vc indica isso na cláusula PARALLEL da tabela/índice , ou pode utilizar o HINT de /*+ PARALLEL no SQL : veja detalhes e referência na documentação Oracle, em especial no manual de Concepts (isso é conceito básico) e no Administrator´s Guide (vários capítulos falam sobre o assunto). Paera encerrar, uma dica : pra qquer um que esteja tentando entender os conceitos e formas de uso (Eficiente!) de databases Oracle eu ** enfaticamente ** Recomendo o livro "Expert Oracle Database Architecture: 9i and 10g Programming Techniques and Solutions", de Thomas Kyte : junto dele vem em CD-ROM a versão anterior, que trata de conceitos mais básicos, chamada "Expert One on One: Oracle" - uma leitura e estudio Cuidadosos desses dois vão te dar uma visão Radicalmente diferente do banco de dados Oracle e suas possibilidades/funcionalidades, eu garanto... []s Chiappa --- Em oracle_br@yahoogrupos.com.br <mailto:oracle_br%40yahoogrupos.com.br> , Samuel Corradi <corrad...@...> escreveu > > Ok. Nao sei se desativar eh uma boa. A pergunta nesse ponto eh: Se todos > serao atualizado, o indice nao tera que ser recriado de qualquer forma?? > Ou o indice soh eh reriado com mudancas na estrutura da tabela? > > Outra duvida, o que eh esse paralelismo? Qual o conceito disso? Como uso? > > Sobre a UNDO, vou criar um datafile maior antes de fazer essa > operacao... (Sim, o DBA sou eu mesmo. rsrs) > > > > > > Em 13-07-2010 16:16, José Laurindo escreveu: > > Sim, pelo que eu entendi vc quer mesmo trabalhar na tabela inteira ( o WHERE é só pra indicar o último registro lido, mas TODOS os registros tem que ser lidos e atualizados pelo que entendi), então sim, vc teria um único UPDATE sem WHERE - apenas, torno a repetir, ANTES DE FAZER ISSo acione o seu DBA para que ele crie uma área de undo/rollback apropriada, ative paralelismo no acesso à essa tabela, avalie se vale a pena desativar o índice e depois fazer o rebuild em NOLOGGING, enfim... > > > > []s > > > > Chiappa > > > > --- Em oracle_br@yahoogrupos.com.br <mailto:oracle_br%40yahoogrupos.com.br> , Samuel Corradi<corradibh@> escreveu > >> > >> Mas como fazer esse comando em um update soh? > >> > >> Voce diz tirar o coteudo do loop e colocar em um UPDATE que NAO tenha a > >> clausula WHERE? > >> > >> ------------------------------------------------- > >> ... > >> LOOP > >> > >> codigo := TRIM(SUBSTR(registro.f14, INSTR(registro.f14,'-',-1) + 2, > >> LENGTH(registro.f14))); > >> > >> nome := TRIM(SUBSTR(registro.f14, 1, INSTR(registro.f14,'-',-1) - 2 )); > >> > >> UPDATE sadig.mod0046 SET f14=nome || '[' || codigo || ']' WHERE > >> f1=registro.f1 and f6=registro.f6; > >> > >> END LOOP; > >> ... > >> ------------------------------------------------- > >> > >> para > >> > >> ------------------------------------------------- > >> > >> UPDATE sadig.mod0046 > >> SET f14=TRIM(SUBSTR(f14, 1, INSTR(f14,'-',-1) - 2 )) || '[' || > >> TRIM(SUBSTR(f14, INSTR(f14,'-',-1) + 2, LENGTH(f14))) || ']'; > >> > >> ------------------------------------------------- > >> > >> > >> Em 12-07-2010 14:54, José Laurindo escreveu: > >>> Oi, Samuel : primeiro de tudo, rigorosamente Não Existe isso de "o script parar" quando redo log file enche : o que pode acontecer nesse sentido é , se o banco est;a programado para arquivar/copiar os redo log files cheios (archive mode) E não há espaço em disco não é a sessão, mas sim o banco TODINHO que para - isso é Bem difícil de acontecer, mas o seu DBA é Totalmente capaz de solucionar isso, uma mensagem BEM ESPECÍFICA é gerada no alert do banco quando isso ocorre... COnsulte o seu DBA pra que isso seja verificado. > >>> Caso não seja esse o caso, aí pra mim o que está acontecendo é simples (e esperada) ** LENTIDÃO ** por causa da (via de regra totalmente INAPROPRIADA) programação e processamento uma iinha/registro por vez que vc está fazendo (também conhecida como row-by-row, oo slow-by-slow, slow aqui por motivos óbvios)... > >>> Se vc quer performance máxima num SQL, dê os recursos necessários e deixa o banco trabalhar : isso implicaria num primiro momento em acionar o DBA, para que ele crie área de rollback/undo suficiente e (se adequado) ative paralelismo e (se possível) desative eventuais triggers e índices (com REBUILD em modo NOLOGGING posterior), E no segundo passo vc JOGA FORA esse loop e faz o comando num UPDATE só, esse é o mantra, é o caminho, é a Melhor Coisa quando vc quer máxima performance num SQL... > >>> Dá uma pesquisada em http://asktom.oracle.com por SQL ROW BY ROW PERFORMANCE que vc acha várias refs e dicas sobre isso... > >>> > >>> []s > >>> > >>> Chiappa > >>> > >>> > >>> --- Em oracle_br@yahoogrupos.com.br <mailto:oracle_br%40yahoogrupos.com.br> , Samuel Corradi<corradibh@> escreveu > >>>> > >>>> Ola pessoal! > >>>> > >>>> Tenho que faz update em um campo do tipo VARCHAR2. > >>>> > >>>> Para isso fiz um PL que abre um cursor e percorrer todas linhas > >>>> alterando os valores. > >>>> > >>>> Agora, estou tendo um problema durante a atualizacao. Aparentemente, os > >>>> redo logs enchem e o sript para. Nao sei dizer exatamente o que estah > >>>> acontecendo, mas acredito que tenho que fazer um controle maior durante > >>>> esse update. > >>>> > >>>> Alguem tem alguma sugestao do que pode estar acontecendo? Alguem jah > >>>> passou por esse trabalho de atualizar muitos registros de uma tabela? > >>>> > >>>> Segue meu PL para referencia: > >>>> > >>>> ================================================ > >>>> > >>>> DECLARE > >>>> CURSOR c1 IS select * from sadig.mod0046; > >>>> flag BOOLEAN DEFAULT false; > >>>> tamanho PLS_INTEGER DEFAULT 0; > >>>> codigo VARCHAR2(45); > >>>> nome VARCHAR2(85); > >>>> BEGIN > >>>> FOR registro IN C1 > >>>> LOOP > >>>> codigo := TRIM(SUBSTR(registro.f14, INSTR(registro.f14,'-',-1) + 2, > >>>> LENGTH(registro.f14))); > >>>> nome := TRIM(SUBSTR(registro.f14, 1, INSTR(registro.f14,'-',-1) - 2 )); > >>>> UPDATE sadig.mod0046 SET f14=nome || '[' || codigo || ']' WHERE > >>>> f1=registro.f1 and f6=registro.f6; > >>>> END LOOP; > >>>> END; > >>>> > >>>> ================================================= > >>>> > >>>> Obrigado! > >>>> > >>> > >>> > >>> > >> > > > > > > > [As partes desta mensagem que não continham texto foram removidas]