我从Oracle sql工具运行一个插入,从各种表中选择大约100.000行,并将它们插入到不同数据库的另一个表中,并以3分钟结束。 我在存储过程或oracle中的PLSQL中尝试相同的查询,我们运行大约2个小时。有关信息,请使用Source Oracle 11g和目标Oracle 10g
存储过程(每个商店大约需要2个小时):
CREATE OR REPLACE PROCEDURE MGS.TRANSFER_DATA(a_date in varchar2) -- yyyymmdd
BEGIN
BEGIN
FOR xx IN(
SELECT STR_CD FROM MGS.STORE ORDER BY STR_CD ASC
) LOOP
CALL_LOG(xx.STR_CD,a_date,sysdate,"START INSERT");
INSERT INTO STOCK@BBS
SELECT
STR_CD, STK.DT, PROD_CD, QTY, ORDER_QTY, ORDER_QTY
FROM
MGS.STOCK STK, MGS.SALE SAL
WHERE STK.STR_CD = xx.STR
AND STK.STR_CD = SAL.STR_CD(+)
AND STK.PROD_CD = SAL.PROD_CD(+)
AND STK.DT = SAL.DT(+)
AND STK.DT = a_date;
CALL_LOG(xx.STR_CD,a_date,sysdate,"INSERT SUCESSFULL");
END LOOP;
END;
END TRANSFER_DATA;
我尝试了1个商店的查询(只花了3分钟):
INSERT INTO STOCK@BBS
SELECT
STR_CD, STK.DT, PROD_CD, QTY, ORDER_QTY, ORDER_QTY
FROM
MGS.STOCK STK, MGS.SALE SAL
WHERE STK.STR_CD = 'STORE01'
AND STK.STR_CD = SAL.STR_CD(+)
AND STK.PROD_CD = SAL.PROD_CD(+)
AND STK.DT= SAL.DT(+)
AND STK.DT= '20120801'; -- yyyymmdd
答案 0 :(得分:2)
我最好的猜测是,在过程中为查询生成的计划与为独立查询生成的计划有很大不同。在独立版本中,你有一些常量,允许优化器做出一些很好的假设。没有常量,优化器就不会继续,因此可能做出一些不同的决定。试试这个:
获取独立查询的执行计划。
获取以下内容的执行计划(它只是用子查询重构子句替换你的循环):
WITH xx AS (SELECT STR_CD, '20120801' AS A_DATE
FROM MGS.STORE ORDER BY STR_CD ASC)
SELECT STR_CD, "DATE", PROD_CD, QTY, ORDER_QTY, ORDER_QTY
FROM MGS.STOCK STK, MGS.SALE SAL
WHERE STK.STR_CD = xx.STR AND
STK.STR_CD = SAL.STR_CD(+) AND
STK.PROD_CD = SAL.PROD_CD(+) AND
STK."DATE" = SAL."DATE"(+) AND
STK."DATE" = xx.A_DATE
(请注意,我必须对名为DATE
的列进行双引号。我很惊讶你没有遇到这个。)比较计划。由于存在子查询因子子句,第二个计划显然与第一个计划不同,但尝试比较匹配元素。特别要查找第一个查询使用索引而第二个查询执行全表扫描的元素。
根据需要向第二个查询添加提示,以使其计划尽可能地与第一个查询匹配。
我认为不太可能的另一种可能性是记录调用是花费时间的地方。对于咧嘴笑,你可能会尝试评论退出,看看是否有效果(我不会期望,但到目前为止,生活中充满了我没想到的事情: - )。
分享并享受。
答案 1 :(得分:1)
我还没有得到答案为什么plsql中的查询变得缓慢,但我有解决方案:
CREATE OR REPLACE PROCEDURE MGS.TRANSFER_DATA(a_date in varchar2) -- yyyymmdd
BEGIN
BEGIN
FOR xx IN(
SELECT STR_CD FROM MGS.STORE ORDER BY STR_CD ASC
) LOOP
CALL_LOG(xx.STR_CD,a_date,sysdate,"START INSERT");
execute immediate '
INSERT INTO STOCK@BBS
SELECT
STR_CD, STK.DT, PROD_CD, QTY, ORDER_QTY, ORDER_QTY
FROM
MGS.STOCK STK, MGS.SALE SAL
WHERE STK.STR_CD = ''' || xx.STR || '''
AND STK.STR_CD = SAL.STR_CD(+)
AND STK.PROD_CD = SAL.PROD_CD(+)
AND STK.DT = SAL.DT(+)
AND STK.DT = ''' || a_date || '''
';
CALL_LOG(xx.STR_CD,a_date,sysdate,"INSERT SUCESSFULL");
END LOOP;
END;
答案 2 :(得分:0)
尝试通过dbms_job为每个商店并行启动所有这些插入。也许它可以实现与传统sql相同的性能。我认为dbms_parallel_execute也可以为您提供帮助,请参阅http://www.oracle-base.com/articles/11g/dbms_parallel_execute_11gR2.php