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

What is more efficient? (SP PL/SQL)

我有一个执行某些事务(插入/更新)的存储过程,想知道这两个选项中的哪一个更有效 运行 "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;

没事吧?或者有更好的方法吗?

选项 #2 肯定更有效,尽管很难说它在您的情况下是否会引人注目。

每个COMMIT需要少量体力I/O; Oracle 必须确保所有数据都写入磁盘,系统更改号 (SCN) 写入磁盘,可能还有其他我不知道的一致性检查。实际上,多个用户需要大量 COMMIT 才能显着降低数据库速度。发生这种情况时,您可能会看到涉及重做、控制文件等的异常等待事件。

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


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