Re: RES: [oracle_br] Performance em Insert

2006-12-04 Por tôpico rbr72
Obrigado pelas respostas pessoal.

É o seguinte, realmente eu entendo que, com o indice, o oracle gera 
redo, etc, etc, essa foi a explicação que eu tinha em mente. Mas é 
que não pareceu ser problema da inserção de dados em si, porque como 
eu disse, foram inseridos poucas linhas, umas 67, e os updates pelo 
trace enviado pelo cliente foram bem rápidos. Para exemplificar, eu 
fiz um teste no XE, se alguem quiser pode testar também. 

Primeiro criei uma tabele com uma pk:

create table teste(id number, valor number)
alter table teste add constraint pk_teste primary key (id)

Depois criei um script para inserir dados nessa tabela:

---
declare
i integer;
PROCEDURE grava(p_id in number, p_valor  in number) is
BEGIN
INSERT INTO teste( id, valor) VALUES ( 1, p_valor);
EXCEPTION WHEN DUP_VAL_ON_INDEX THEN
UPDATE  teste
SET  valor = valor + p_valor
WHERE id = p_id;
END;

begin
dbms_output.put_line('INICIO: ' || TO_CHAR(SYSDATE, 'DD/MM/ 
HH24:MI:SS'));
for i in 1 .. 2000 loop
grava(1, 1);
end loop;
dbms_output.put_line('FIM: ' || TO_CHAR(SYSDATE, 'DD/MM/ 
HH24:MI:SS'));
end;


Executando esse script, demorou uns 40 segundos aqui na minha 
máquina. Ai fiz o seguinte teste:

alter table teste disable constraint pk_teste
CREATE INDEX idx_teste ON teste ( id )

E mudei o script para o seguinte:
-
declare
i integer;
PROCEDURE grava(p_id in number, p_valor  in number) is
v_achou varchar2(10);
BEGIN
BEGIN
SELECT 'TRUE' INTO v_achou FROM teste WHERE id = p_id;
EXCEPTION WHEN NO_DATA_FOUND THEN
v_achou := 'FALSE';
END;
if v_achou = 'FALSE' then
INSERT INTO teste( id, valor) VALUES ( 1, p_valor);
else
UPDATE  teste
SET  valor = valor + p_valor
WHERE id = p_id;
end if;
END;

begin
dbms_output.put_line('INICIO: ' || TO_CHAR(SYSDATE, 'DD/MM/ 
HH24:MI:SS'));
for i in 1 .. 2000 loop
grava(1, 1);
end loop;
dbms_output.put_line('FIM: ' || TO_CHAR(SYSDATE, 'DD/MM/ 
HH24:MI:SS'));
end;


Esse segundo script demorou 1 segundo. Como podem ver, a única 
mudança foi tirar a pk e colocar somente o indice no lugar, e fazer 
a verificação "manualmente" antes de inserir os dados. Nos 2 
scripts, foram feitos 1 insert e 1999 updates, portanto, acho que 
deveria gerar os mesmos números de redos, etc. Inclusive, no segundo 
script tem indice pra atualizar também. O problema parece estar na 
pk, não sei se para o oracle validar um insert ele executa algumas 
tarefas a mais, sei lá, foi por isso que enviei a mensagem, pra ver 
se vocês poderiam explicar o porque disso.

Quanto as dicas que deram, acho que não é problema de rebuild do 
indice, pois no exemplo que fiz, numa base totalmente limpa, a 
difereça de performance é brutal. Quanto as dicas do Chiappa, 
infelizmente não da pra fazer somente num select, tem que ser 
procedure mesmo porque existem muitas consistencias antes da 
gravação, e tem que ser gravado mesmo numa tabela, pois ela vai ser 
lido por um outro sistema e eles exigiram que fosse dessa maneira.

Bem, o problema na verdade está resolvido, eu mandei a mensagem 
mesmo pra tentar entender porque da pk ser mais lento. Talvez eu 
esteja fazendo besteira nesses testes que fiz também, se tiver podem 
falar, hehe.

Abraços



[oracle_br] Performance em Insert

2006-12-01 Por tôpico rbr72
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