Seguinte : sim, por DEFINIÇÃO quando vc cria um índice vc em muitos casos GANHA performance nas consultas, mas isso TEM A OUTRA FACE de implicar em diminuição de performance dos DMLs, já que a CADA DML feito o índice tem que ser atualizado (e índices são estruturas COMPLEXAS, que obrigatoriamente TEM QUE estarem fisicamente ordenados, é custoso atualizar índices) - isso está claramente exposto no manual "Oracle Concepts", que recomendo o estudo. Muito bem, continuando : no caso em questão vc está querendo introduzir um GRANDE volume de dados, PORTANTO isso é uma CARGA DE DADOS, uma rotina onde (claro) vc quer ter a maior performance possível em DMLs para que ela termine o quanto antes, pois NINGUÉM tem acesso aos dados antes deles carregarem... Em rotinas do tipo, SIM, é COMUM e RECOMENDADO vc desabilitar índices e constraints, justamente para EVITAR de "pagar o preço" do overhead a cada DML (ao final da rotina vc rebuilda os índices - em paralelo e nologging se possível -, desta menaira "pagando o preço" duma vez só, á vista tem desconto :_) , isso se deve PRINCIPALMENTE ao fato de que, SEM índices presentes, vc tem acesso ao modo NOLOGGING, que muitas vezes representa um ABSURDAMENTE ENORME ganho em performance, é técnica PADRÂO em bancos DW/batch, pesquise em http://asktom.oracle.com que vc acha diversos artigos e testes demonstrando isso. ==> Afora esse ponto, que vc DEVERÀ SIM implementar se minimamente possível, observo que :
- a técnica de insert into tabela values ... exception when dup_val_on_index update tabela set ==> é a PIOR DAS PIORES possíveis, pois vc FAZ o insert, gerando redo e undo, que se for duplicação VAI ser desfeito, gerando mais redo e tendo que ler o undo, ALTOS I/Os aí... Sem sombra de dúvida, se a sua versão de banco já tem e aceita, o comando SQL de MERGE seria ULTRA mais eficiente - preferencialmente faz essa carga com uma ferramenta que gere SQL e envie diretamente esse SQL pro banco, em PL/SQL a cada SQL enviado pro banco vc PAGA UM PREÇO na forma de context switch, pra uns poucoas registros isso não é nada, MAS pra um grande volume rapidamente isso se torna HORRÍVEL, SQL direto é a melhor solução : se a carga é de um aqruivo-texto (tipicamente é) no banco 9i em diante vc tem INCLUSIVE a chance de usar o arquivo-texto como se fosse uma tabela, com a opção de EXTERNAL TABLE, aí o MERGE seria ainda mais eficiente... e finalmente : SE realmente for (por qquer motivo) absolutamente, completamente, inequivocadamente impossível vc fazer em SQL apenas e tiver que usar PL/SQL, que AO MENOS vc use array processing e bulk collect, é isso. []s Chiappa --- Em oracle_br@yahoogrupos.com.br, "rbr72" <[EMAIL PROTECTED]> escreveu > > Pessoal, tava analisando um problema num cliente, e percebi que o > processo mais demorado era um insert executado várias vezes numa > tabela. A lógica era mais ou menos essa abaixo, se já existia um > dado na tabela, era feito um update de valores. > > insert into tabela values ... > exception when dup_val_on_index > update tabela set ... > > No trace gerado pelo cliente, ele tentou executar 56000 inserts, > foram gravados somente 56 linhas, o resto foi tudo pro update. O > problema que pra executar os 56000 inserts demorou 300 segundos, os > updates foram bem rápidos. > > Fazendo os testes, o problema era a primary key, eu desabilitei ela, > criei um indice normal, e fiz a verificacao se o registro existe, > faco update, senão, insert. Desse modo ficou bem rápido também. > > O que eu gostaria de saber é a explicação pra isso, sei que, com a > primary key, é necessário atualizar o arquivo de indice a cada > insert. Mas no cliente só gravou 56 inserts, então conclui que o > problema em alguma verificação que a primary key força o oracle a > fazer. Alguém sabe o que o Oracle realiza nos inserts, e o porque da > demora? Outra coisa, tem como fazer o insert ficar mais rápido ou > uma solução melhor do que desabilitiar a pk? Se alguém tiver idéia > melhor ajuda, porque vou ter que alterar um monte de procedures. :-) > > Obrigado >