我运行 Oracle sql 工具的插入,该工具从各个表中选择大约 100.000 行,并将它们插入到不同数据库的另一个表中,这在 3 分钟内结束。 我在 Oracle 的存储过程或 PLSQL 中尝试相同的查询,运行了大约 2 小时。有关信息,我使用源 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;
结束 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
最佳答案
我的最佳猜测是,为过程中的查询生成的计划与为独立查询生成的计划有很大不同。在独立版本中,您可以使用常量让优化器做出一些好的假设。如果没有常量,优化器就没有什么可继续进行的,因此可能会做出一些不同的决定。试试这个:
获取独立查询的执行计划。
获取以下内容的执行计划(它只是用子查询重构子句替换循环):
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
的列。我很惊讶您没有遇到这种情况)。比较计划。由于子查询分解子句的存在,第二个计划显然与第一个计划不同,但尝试比较匹配的元素。特别是查找第一个查询使用索引而第二个查询执行全表扫描的元素。
根据需要向第二个查询添加提示,使其计划尽可能与第一个查询匹配。
另一种可能性(我认为不太可能)是日志记录调用是花费时间的地方。对于笑容,你可以尝试评论注销,看看这是否有效果(这是我没想到的,但到目前为止,生活充满了我没想到的事情:-)。
分享并享受。
关于database - (oracle) 与手动运行插入相比,在存储过程中插入非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12316124/