2017-04-13 61 views
0

现在我面临着一个优化问题。 我有一个列表(17000+),其中一些不活跃。该列表由客户端提供给EXCEL文件,他要求我重新发送它们(明显只有那些活动的)。SQL优化

为此,我必须根据客户提供的清单过滤生产数据库。不幸的是,我无法将列表加载到生产的一张表中,然后加入主文章表中,但是我可以将其转换为UAT数据库,并与生产数据库链接。

生产商品主数据包含200个000 000多个行,但将其过滤,我可以redure至约80 000 000

我命令中检索只从生产活性制品,想到使用集合但它似乎最后一个过滤器太长了。

这里是我的代码:

declare 
    type t_art is table of number index by pls_integer; 
    v_art t_art; 
    v_filtered t_art; 
    idx number := 0; 
begin 
    for i in (select * from [email protected]_DATABASE) 
    loop 
    idx := idx + 1; 
     v_art(idx) := i.art_nr; 
    end loop; 

    for j in v_art.first .. v_art.last 
    loop 
     select distinct art_nr 
     bulk collect into v_filtered 
     from production_article_master_data 
     where status = 0 -- status is active 
     and sperr_stat in (0, 2) 
     and trunc(valid_until) >= trunc(sysdate) 
     and art_nr = v_art(j); 
    end loop; 
end; 

说明:从UAT数据库,通过DBLINK,我insertinting列表到生产(v_art)关联数组。然后,对于v_art中的每个值(17000+ distinct articles),我将使用生产文章主数据进行过滤,并在第二个ASSOCITIAVE ARRAY中返回仅有效文章(可能为6-8000)。

不幸的是,这种过滤操作需要数小时。 有人可以提供一些提示,如何改进这orde减少执行时间,请?

谢谢

+0

使用集合在一个循环像这样做将不起作用,因为每次迭代调用'BULK COLLECT INTO'时,'v_filtered'集合将被重新初始化为一个新的(空)集合。 – MT0

回答

2

只需使用SQL和连接两个表:

select distinct p.art_nr 
from production_article_master_data p 
     INNER JOIN 
     [email protected]_DATABASE t 
     ON (p.art_nr = t.art_nr) 
where status = 0 -- status is active 
and sperr_stat in (0, 2) 
and trunc(valid_until) >= trunc(sysdate) 

如果你必须这样做,在PL/SQL,则:

CREATE OR REPLACE TYPE numberlist IS TABLE OF NUMBER; 
/

declare 
    -- If you are using Oracle 12c you should be able to declare the 
    -- type in the PL/SQL block. In earlier versions you will need to 
    -- declare it in the SQL scope instead. 

    -- TYPE numberlist IS TABLE OF NUMBER; 

    v_art  NUMBERLIST; 
    v_filtered NUMBERLIST; 
begin 
    select art_nr 
    BULK COLLECT INTO v_art 
    from [email protected]_DATABASE; 

    select distinct art_nr 
    bulk collect into v_filtered 
    from production_article_master_data 
    where status = 0 -- status is active 
    and sperr_stat in (0, 2) 
    and trunc(valid_until) >= trunc(sysdate) 
    and art_nr MEMBER OF v_art; 
end; 
+0

你确定通过DBLink连接2个表是最好的解决方案(考虑到第一个表非常大)?! – mikcutu

+0

@mikcutu我还添加了一个不依赖循环的PL/SQL版本。我无法告诉你什么会更高性能,因为我无法访问数据库和网络 - 所以您需要尝试各种选项并查看。 – MT0

+0

数据库版本是11.1.0.7.0
我不允许在生产数据库上创建对象
...但似乎通过DBLink的选择在时间上成功完成。 – mikcutu