Bom dia pessoal! sou iniciante em oracle, e me surgiu uma dúvida!
tenho um cursor e faço um fetch normal nele abrindo e fechando tal...
se eu usar uma bulk nesse cursor o desempnho será melhor???
se alguém tiver alguma maneira melhor, em questão de performace, para usar cursor me ajude por favor! hehehe
abraços
cursoe e BULK COLLECT melhor performace??
-
- Rank: Programador Pleno
- Mensagens: 34
- Registrado em: Qua, 02 Set 2009 3:29 pm
- Localização: São José - SC
- fsitja
- Rank: OraSauro
- Mensagens: 611
- Registrado em: Seg, 19 Jan 2009 4:29 pm
- Localização: Gaúcho no Rio de Janeiro - RJ
"The scars exist to remind us that the past was real"
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html
OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html
OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist
Está correto, bulk collect + forall é mais rápido que row-by-row no cursor, por que há menos chaveamento de contexto entre os engines de SQL e de PL/SQL.
Entretanto, fazer em SQL puro num único comando é, como regra geral, a melhor alternativa em desempenho. PL/SQL só quando não for possível em SQL. E é possível muita coisa em SQL, principalmente com as extensões que a Oracle oferece.
Entretanto, fazer em SQL puro num único comando é, como regra geral, a melhor alternativa em desempenho. PL/SQL só quando não for possível em SQL. E é possível muita coisa em SQL, principalmente com as extensões que a Oracle oferece.
-
- Rank: Programador Pleno
- Mensagens: 34
- Registrado em: Qua, 02 Set 2009 3:29 pm
- Localização: São José - SC
Hmn!!
vou incomodar mais um pouquinho, hehehe.
entenda o que está sendo feito e me diga no que estou errando eheheh:
assim é só um exemplo, não é o codigo verdadeiro, mas qual maneira de melhorar a performace no que está sendo feito, não conheço muito ai fico meio na dúvida de como fazer!!
tenho os cursores
vou incomodar mais um pouquinho, hehehe.
entenda o que está sendo feito e me diga no que estou errando eheheh:
assim é só um exemplo, não é o codigo verdadeiro, mas qual maneira de melhorar a performace no que está sendo feito, não conheço muito ai fico meio na dúvida de como fazer!!
tenho os cursores
--Declarando o Cursor (apenas exemplo)
CURSOR c_Cur1(v_Ini DATE, v_Fim DATE) IS
SELECT campo1, campo2, campo3, campo4, campo5
FROM T_TABELA
WHERE campoTab > v_Ini AND campoTab <= v_Fim) ;
CURSOR c_Curs2(v_Cod NUMBER) IS
SELECT a.campo1 ,a.campo2 ,b.campo1 ,b.campo2
FROM tabela1 a, tabela2 b
WHERE a.campo1 = v_cod AND b.campo1 = v_cod ;
--corpo do código
FOR r_Test1 IN c_Cur1(v_IniProcess, v_FimProcess) LOOP
OPEN c_Curs2(r_Test1.campo1);
FETCH c_Curs2 INTO v_var1, v_var2, var3, var4;
CLOSE c_Curs2;
--Aqui faz um insert dos dados obtidos no c_curs2
END LOOP;
- fsitja
- Rank: OraSauro
- Mensagens: 611
- Registrado em: Seg, 19 Jan 2009 4:29 pm
- Localização: Gaúcho no Rio de Janeiro - RJ
"The scars exist to remind us that the past was real"
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html
OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html
OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist
Eu tenho a impressão que daria para resolver tudo num único comando de insert.
Tipo:
Depende da cardinalidade do relacionamento entre t_tabela, tabela1 e tabela2. Se houver mais de um registro em t_tabela para cada em tabela1 e tabela2, pode precisar de um group by numa subquery do from, ou um exists no where, para evitar linhas duplicadas.
Caso eu tenha palpitado errado no modelo de dados, com a estrutura das tabelas (colunas, pk, fk) mais dados de exemplo dá para ter uma noção melhor.
Tipo:
insert into tabela_destino (col1, col2, col3, etc)
select col1, col2, col3, etc -- conforme a lista acima
from t_tabela t
join tabela1 a on a.campo1 = t.campo1
join tabela2 b on b.campo1 = t.campo1
where t.campoTab > :v_Ini AND t.campoTab <= :v_Fim
Caso eu tenha palpitado errado no modelo de dados, com a estrutura das tabelas (colunas, pk, fk) mais dados de exemplo dá para ter uma noção melhor.
-
- Rank: Programador Pleno
- Mensagens: 34
- Registrado em: Qua, 02 Set 2009 3:29 pm
- Localização: São José - SC
mas assim, e a questao do loop ?
tipo pra cada registro encontrado na tabela do cursor 1 ele teria que abrir o cursor 2 buscar alguns dados e dpois fazer o insert...
outra coisa no seu código você coloca :v_ini por exemplo o " : " antes da variavel melhora o desempenho??
tipo pra cada registro encontrado na tabela do cursor 1 ele teria que abrir o cursor 2 buscar alguns dados e dpois fazer o insert...
outra coisa no seu código você coloca :v_ini por exemplo o " : " antes da variavel melhora o desempenho??
- fsitja
- Rank: OraSauro
- Mensagens: 611
- Registrado em: Seg, 19 Jan 2009 4:29 pm
- Localização: Gaúcho no Rio de Janeiro - RJ
"The scars exist to remind us that the past was real"
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html
OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html
OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist
O que eu quis dizer é que não precisaria de loop. Com um select você produz o mesmo resultado através de joins (operações sobre conjuntos). A menos que você tenha alguma outra operação feita no loop, além de inserir. Nesse caso teria que reavaliar.
O :v_ini indica que é criado uma "bind variable" (variável de ligação). Basicamente é um parâmetro, que diz para o Oracle que aquele SQL pode ser reaproveitado apenas indicando o parâmetro novo.
Se você implementar numa procedure, você pode substituir por uma variável PL/SQL qualquer, se chegar à conclusão que a procedure não vai ser executada centenas de vezes e não haverá reaproveitamento do SQL.
O :v_ini indica que é criado uma "bind variable" (variável de ligação). Basicamente é um parâmetro, que diz para o Oracle que aquele SQL pode ser reaproveitado apenas indicando o parâmetro novo.
Se você implementar numa procedure, você pode substituir por uma variável PL/SQL qualquer, se chegar à conclusão que a procedure não vai ser executada centenas de vezes e não haverá reaproveitamento do SQL.
- dr_gori
- Moderador
- Mensagens: 5018
- Registrado em: Seg, 03 Mai 2004 3:08 pm
- Localização: Portland, OR USA
- Contato:
Thomas F. G
Você já respondeu a dúvida de alguém hoje?
https://glufke.net/oracle/search.php?search_id=unanswered
Você já respondeu a dúvida de alguém hoje?
https://glufke.net/oracle/search.php?search_id=unanswered
Só pra complementar: o "motivo" dos bulks serem rápidos é que eles ficam na memória. Então, você até consegue acelerar um cursor, mas com um preço alto! (vai gastar memória). E as vezes não se tem muito sobrando.
Por isso que deve sempre ser bem avaliado o uso dos bulks, pois nem sempre é a solução. Como foi falado pelo fsitja, o ideal é tentar fazer num comando SQL. Se não dá, dai sim vai pro PL.
Por isso que deve sempre ser bem avaliado o uso dos bulks, pois nem sempre é a solução. Como foi falado pelo fsitja, o ideal é tentar fazer num comando SQL. Se não dá, dai sim vai pro PL.
- fsitja
- Rank: OraSauro
- Mensagens: 611
- Registrado em: Seg, 19 Jan 2009 4:29 pm
- Localização: Gaúcho no Rio de Janeiro - RJ
"The scars exist to remind us that the past was real"
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html
OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html
OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist
Citando o mestre Tom Kyte, usar um collection de 100 registros em memória é razoável, 1000 já é extremo.
http://asktom.oracle.com/pls/asktom/f?p ... 8938803188
http://asktom.oracle.com/pls/asktom/f?p ... 8938803188
and we said...
good gosh -- you aren't serious are you???
Use the LIMIT clause, bulk collect say 100 to 1000 rows -- process them, bulk insert
them, get the next 100/1000 rows.
You blew process memory -- not SGA. Your process got bigger then your OS would allow you
(you hit an OS limit, might be ulimit related or whatever).
do something like this:
open cursor; loop fetch c bulk collect into l_c1, l_c2, ....... LIMIT 1000; for i in 1 .. l_c1.count loop process.... end loop; forall i in 1 .. l_c1.count insert into ..... values ( L_c1(i), .... ); end loop; exit when c%notfound; end loop; close cursor 1000 would be extreme, 100 is reasonable.
-
- Rank: Estagiário Pleno
- Mensagens: 3
- Registrado em: Sáb, 02 Out 2010 5:11 pm
- Localização: SP
Ola pessoal estou com uma dúvida referente a Bulk collect com for all
segue um pequeno exemplo:
dessa maneira funciona perfeitamente, o problema é quando tento especificar apenas alguns campos no select do cursor ao invés de fazer um select com *, por exemplo:
aparece um erro dizendo que número incorreto de valores na lista até ai eu entendi, porque a minha coleção está pegando a estrutura de uma tabela.
ai então eu faço a coleção pegar a estrutura do cursor:
ai o erro cai para a linha do insert, dizendo que não valores suficientes
erro nessa linha
pois minha intenção é utilizar o forall para fazer o insert de uma massa de dados, porem não será em todos os campos da tabela
será se alguém pode me ajudar;
segue um pequeno exemplo:
CREATE OR replace PROCEDURE Test
IS
CURSOR c1 IS
SELECT *
FROM cliente;
TYPE c_collect
IS TABLE OF cliente2%ROWTYPE;
colecao C_COLLECT;
BEGIN
OPEN c1;
LOOP
FETCH c1 bulk collect INTO colecao;
exit WHEN colecao.count = 0;
forall i IN 1..colecao.count
INSERT INTO cliente2
VALUES Colecao(i);
END LOOP;
END;
create or replace procedure test is
CURSOR c1 IS
SELECT id,
nome,
sobrenome
FROM cliente;type c_collect
IS
TABLE OF cliente2%ROWTYPE;colecao c_collect;BEGIN
OPEN c1;
LOOP
FETCH c1 bulk collect
INTO colecao;
EXIT
WHEN colecao.count = 0;
forall i IN 1..colecao.count
INSERT INTO cliente2 VALUES Colecao
(
i
);
END LOOP;
END;
ai então eu faço a coleção pegar a estrutura do cursor:
cursor c1 is select id, nome, sobrenome from cliente;
type c_collect is table of c1%rowtype;
forall i in 1..colecao.count
insert into cliente2 values colecao(i);
pois minha intenção é utilizar o forall para fazer o insert de uma massa de dados, porem não será em todos os campos da tabela
será se alguém pode me ajudar;
- fsitja
- Rank: OraSauro
- Mensagens: 611
- Registrado em: Seg, 19 Jan 2009 4:29 pm
- Localização: Gaúcho no Rio de Janeiro - RJ
"The scars exist to remind us that the past was real"
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html
OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html
OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist
Olá,
Provavelmente porque ele está esperando que cheguem todas as colunas tabela CLIENTE2. Tente especificar as colunas assim:
Provavelmente porque ele está esperando que cheguem todas as colunas tabela CLIENTE2. Tente especificar as colunas assim:
insert into cliente2 (id, nome, sobrenome) values colecao(i);
-
- Rank: Estagiário Pleno
- Mensagens: 3
- Registrado em: Sáb, 02 Out 2010 5:11 pm
- Localização: SP
Consegui resolver, na verdade é necessário criar os types relativos as colunas, ex se for selecionar 3 colunas, e necessário criar 3 types e tb informa-los no insert
insert into tabela (col1, col2, col3) values(type1(), type2(), type4())
-
- Informação
-
Quem está online
Usuários navegando neste fórum: Nenhum usuário registrado e 4 visitantes