简化一下就是这样,loop里有6个相似的过程,我就写了一个了 CURSOR c1 LOOP OPEN xzzdz_cursor FOR SELECT dzbh,xxdz FROM ent_wszz.ENTITY_DZ t1 WHERE t1.xxdz = v_xzz; FETCH xzzdz_cursor INTO xzzdz_record; IF(..) THEN SELECT COUNT(1) INTO d_flag FROM ENT_WSZZ.ENTITY_link WHERE stabh='..' AND stbbh='...'; IF(d_flag= 0) THEN INSERT INTO......END LOOP
首先,你根据每条查询的30、50毫秒来推测执行12次的时间是不准的,因为单条查询的时间包括硬解析、软解析时间,所以单次时间参考性不大。 其次,你可以在循环中批量commit,例如1万条commit一次,提升性能。 再次,优化你的查询、更新SQL,增加索引、使用merge等方法来提升更新性能。下面给你个例子吧: MERGE INTO TAB1 A USING TAB2 B ON (A.POLICY_NO = B.POLICY_NO) WHEN MATCHED THEN UPDATE SET A.PLAN_CODE = B.PLAN_CODE, A.UPDATED_DATE = SYSDATE, A.UPDATED_BY = 'SYSTEM' WHEN NOT MATCHED THEN INSERT VALUES (B.POLICY_NO, 'SYSTEM');
-- 尤其是存储过程中存在循环或变量赋值的时候,必须有个“上下文切换”操作过程,也需要耗费一定的时间!
-- 所谓“上下文切换”是指在存储过程中Oracle从SQL环境切换到PL/SQL环境!
另外可以用job实现存储过程的并行执行
CURSOR c1
LOOP
OPEN xzzdz_cursor FOR
SELECT dzbh,xxdz FROM ent_wszz.ENTITY_DZ t1 WHERE t1.xxdz = v_xzz;
FETCH xzzdz_cursor INTO xzzdz_record; IF(..) THEN
SELECT COUNT(1) INTO d_flag FROM ENT_WSZZ.ENTITY_link
WHERE stabh='..' AND stbbh='...';
IF(d_flag= 0) THEN
INSERT INTO......END LOOP
ENTITY_DZ 暂时1000万数据
ENTITY_link 暂时4000万数据
其次,你可以在循环中批量commit,例如1万条commit一次,提升性能。
再次,优化你的查询、更新SQL,增加索引、使用merge等方法来提升更新性能。下面给你个例子吧:
MERGE INTO TAB1 A
USING TAB2 B
ON (A.POLICY_NO = B.POLICY_NO)
WHEN MATCHED THEN
UPDATE
SET A.PLAN_CODE = B.PLAN_CODE,
A.UPDATED_DATE = SYSDATE,
A.UPDATED_BY = 'SYSTEM'
WHEN NOT MATCHED THEN
INSERT VALUES (B.POLICY_NO, 'SYSTEM');
如5楼的,可以存一些数据测试看看。测试时可以没执行一条语句都print时间看看。再改进。鉴于你的数据量非常大:
c1 800多万
ENTITY_DZ 暂时1000万数据
ENTITY_link 暂时4000万数据应该考虑拆分任务,比如一个存储器处理一部分表,或者一部分任务。必要时服务器的计算能力也不够,可以考虑复制到其他服务器上去预先处理。这是我采用的方法。曾经写过一个存储器需要运行几个小时,在晚间,数据量也在千万条。
也可以计算出一些中间结果,以减少存储器处理时的数量量。