什么更有效? (SP PL / SQL)

时间:2015-02-12 18:59:01

标签: oracle stored-procedures plsql commit

我有一个执行某些事务(插入/更新)的存储过程,并希望知道这两个选项中哪一个更有效地运行“COMMIT”

选项1:

     BEGIN        
          OPEN myCursor;
            LOOP               
                FETCH myCursor INTO AUX_ID, AUX_VAR1, AUX_VAR2;
                  EXIT WHEN myCursor%NOTFOUND;   

                      SELECT count(*) INTO myCount   FROM myTable    WHERE code = AUX_ID;

                      IF myCount > 0 THEN
                          UPDATE myTable
                          SET VAR1 = AUX_VAR1, VAR2 = AUX_VAR2
                          WHERE code = AUX_ID_BD;
                          COMMIT;
                      ELSE
                          INSERT INTO myTable(code, VAR1, VAR2)
                          VALUES(AUX_ID, AUX_VAR1, AUX_VAR2)
                          COMMIT;
                      END IF;              
            END LOOP;
          CLOSE myCursor;    
     END;

选项2:

          BEGIN        
          OPEN myCursor;
            LOOP               
                FETCH myCursor INTO AUX_ID, AUX_VAR1, AUX_VAR2;
                  EXIT WHEN myCursor%NOTFOUND;   

                      SELECT count(*) INTO myCount   FROM myTable    WHERE code = AUX_ID;

                      IF myCount > 0 THEN
                          UPDATE myTable
                          SET VAR1 = AUX_VAR1, VAR2 = AUX_VAR2
                          WHERE code = AUX_ID_BD;
                      ELSE
                          INSERT INTO myTable(code, VAR1, VAR2)
                          VALUES(AUX_ID, AUX_VAR1, AUX_VAR2)
                      END IF;              
            END LOOP;
            COMMIT;
          CLOSE myCursor;    
     END;

没关系?还是有更好的方法?

1 个答案:

答案 0 :(得分:3)

选项#2肯定更有效率,虽然在你的情况下很难判断它是否会引人注意。

每个COMMIT需要少量的物理I / O; Oracle必须确保将所有数据写入磁盘,将系统更改号(SCN)写入磁盘,并且可能还有其他一些我不知道的一致性检查。实际上,来自多个用户需要大量COMMIT来显着减慢数据库的速度。当发生这种情况时,您可能会看到涉及REDO,控制文件等的异常等待事件。

在发出COMMIT之前,Oracle可以在内存中或异步进行更改。这可能会使性能为equivalent to an in-memory database


更好的选择是完全通过使用单个MERGE语句来避免这个问题,正如Sylvain Leroux建议的那样。如果必须在PL / SQL中完成处理,至少用更简单的游标FOR-loop替换OPEN / FETCH游标语法。游标FOR循环将自动批量收集数据,从而显着提高读取性能。

相关问题