在PLSQL中缓慢循环

时间:2014-04-11 09:59:03

标签: performance loops select plsql insert

这个查询太慢你能帮助我加快速度吗?查询使用'选择其中'来插入MB_TXDV_042014数据。节点类似于t.num_sequencial上每个值的过滤器。我需要从一些表中提取数据到MB_TXDV_042014,但我不想为这些进程使用太多内存。

由于

How do i speed this up guys?

DECLARE
    counter NUMBER;

BEGIN

FOR counter IN 1..1000000
LOOP
insert into MB_TXDV_042014
    (cod_unidade, num_sequencial, num_taxa, quant, modulo, num_episodio, data, designacao, valor_acto)
select sh.cod_unidade, t.num_sequencial,t.num_taxa,1 quant, 'CON' modulo,c.con_episodio episodio, c.dta_realizacao data, 'Consulta Externa' des_adm, nvl(t.valor_acto, 0) valor
from ide_taxas t,con_registadas c, sys_hospital sh, ide_controle ic
where c.num_taxa = t.num_taxa
   and t.tipo_taxa = '2'
   and t.taxa='S'
   and t.num_episodio is not null
   and c.dta_realizacao >= to_date('01-01-2012','dd-mm-yyyy')
   and c.dta_realizacao < to_date('10-04-2014','dd-mm-yyyy')
   and t.num_sequencial = ic.num_sequencial(+)
   and t.num_sequencial = counter
   and ic.dta_obito is null;
   COMMIT;
END LOOP;

END;

2 个答案:

答案 0 :(得分:2)

您似乎不需要循环。为什么你不能这样做:

insert into MB_TXDV_042014
    (cod_unidade, num_sequencial, num_taxa, quant, modulo, 
     num_episodio, data, designacao, valor_acto
    )
    select sh.cod_unidade, t.num_sequencial,t.num_taxa,1 quant, 'CON' modulo,
           c.con_episodio episodio, c.dta_realizacao data, 'Consulta Externa' des_adm, 
           nvl(t.valor_acto, 0) valor
        from ide_taxas t,con_registadas c, sys_hospital sh, ide_controle ic
        where c.num_taxa = t.num_taxa
            and t.tipo_taxa = '2'
            and t.taxa='S'
            and t.num_episodio is not null
            and c.dta_realizacao >= to_date('01-01-2012','dd-mm-yyyy')
            and c.dta_realizacao < to_date('10-04-2014','dd-mm-yyyy')
            and t.num_sequencial = ic.num_sequencial(+)
            and t.num_sequencial <= 1000000
            and ic.dta_obito is null;

答案 1 :(得分:0)

查询中的大象在每一行都提交。这不能快速&#34;。

dan1111是最好的答案,因为它不会更快。 (sql和plsql之间没有引擎切换和数据复制)。

您的替代方案是: 1.批量收集 2. dbms_parallel_execute

在您的情况下,我会调查dbms_parallel_execute,块大小为1.

这是一个批量收集版本,不保证:

DECLARE TYPE rec IS RECORD( cod_unidade ide_controle%TYPE, num_sequencial ide_taxas.num_sequencial%TYPE, num_taxa ide_taxas%TYPE, quant NUMBER, modulo VARCHAR2, episodio con_registadas.con_episodio%TYPE, dta_realizacao con_registadas.dta_realizacao%TYPE, des_adm VARCHAR2, valor ide_taxas.valor_actor%TYPE);

TYPE col IS TABLE OF rec; lines col;

BEGIN

SELECT sh.cod_unidade, t.num_sequencial, t.num_taxa, 1 quant, 'CON' modulo, c.con_episodio episodio, c.dta_realizacao data, 'Consulta Externa' des_adm, NVL(t.valor_acto, 0) valor BULK COLLECT INTO lines FROM ide_taxas t, con_registadas c, sys_hospital sh, ide_controle ic WHERE c.num_taxa = t.num_taxa AND t.tipo_taxa = '2' AND t.taxa = 'S' AND t.num_episodio IS NOT NULL AND c.dta_realizacao >= TO_DATE('01-01-2012', 'dd-mm-yyyy') AND c.dta_realizacao < TO_DATE('10-04-2014', 'dd-mm-yyyy') AND t.num_sequencial = ic.num_sequencial(+) AND t.num_sequencial <= 1000000 AND ic.dta_obito IS NULL; FORALL 1 IN 1 .. lines.count INSERT INTO mb_txdv_042014 (cod_unidade, num_sequencial, num_taxa, quant, modulo, num_episodio, data, designacao, valor_acto) VALUES lines(i);

/* -- normal way. FORALL 1 IN 1 .. lines.count INSERT INTO mb_txdv_042014 (cod_unidade, num_sequencial, num_taxa, quant, modulo, num_episodio, data, designacao, valor_acto) VALUES lines(i); */

FOR i IN 1 .. lines.count LOOP INSERT INTO mb_txdv_042014 (cod_unidade, num_sequencial, num_taxa, quant, modulo, num_episodio, data, designacao, valor_acto) VALUES lines(i); COMMIT; END LOOP;

END;

至少你执行一次选择,而不是一百万次,并且更有效率(将完成更少的解析,并且将使用缓冲区)。

编辑:jeff,修复您的fraking编辑器&gt;&lt;。