嵌套游标性能调优

Nested cursor performance tuning

我有 2 个游标,一个用于从 table 的 50 列和 10,000 多个数据中获取记录,另一个用于检查特定列是否存在于另一个大 table(200 万数据)中.我应该将游标 1 中一年的所有记录写入一个文件,如果该列存在于游标 2 中,那么我应该打印一条存在的错误消息,而不是删除它们。如果它不存在,那么我应该删除该行并将其写入与删除记录相同的文件和消息。 我使用了嵌套游标,性能太差了,因为它每次都处理游标 1 和游标 2 的每一行。

       CURSOR cursor1
         IS           
             select a.* ,a.rowid
              FROM table1 a 
              WHERE a.table1.year = p_year;
    
    CURSOR check_c2(lv_cd )
     IS
      Select DISTINCT 'Y' 
       from table2
       where table2 ='R'
       AND table2.year= p_year
       and table2_code= lv_cd ;

BEGIN :
   FOR r in cursor1 LOOP
            EXIT WHEN cursor1%NOTFOUND;
        
              OPEN check_c2(r.cd);
              FETCH check_c2 INTO lv_check;
                IF check_c2%NOTFOUND THEN
                    lv_check :='N';
                END IF;
                CLOSE check_c2;
       
                  IF lv_check ='Y' THEN
                   lv_msg =(r.col1,r.col2....r.col50, R code exists do not delete)
                   utl_file.put_line(lv_log_file, lv_msg, autoflush=>TRUE);
                   
                ELSE 
                  DELETE from table1 where rowid= r.rowid
                  lv_msg =(r.col1,r.col2....r.col50, delete row)
                   utl_file.put_line(lv_log_file, lv_msg, autoflush=>TRUE);
                   END IF;
                   END LOOP;

这个怎么样?三步操作:

第 1 步:“保存”稍后将删除的行

create table log_table as
select *
from table1 a
where exists (select null
              from table2 b
              where b.year = a.year
                and b.code = a.code
             );

第 2 步:删除行:

delete from table1 a
where exists (select null
              from table2 b
              where b.year = a.year
                and b.code = a.code
             );

第 3 步:如果必须,将 LOG_TABLE 中保存的行存储到您的文件中。如果没有,请将它们留在 LOG_TABLE.

循环中的

utl_file.put_line 将是一个 overhead.Try 附加到 lv_msg 直到字符串的长度为 32767 字节并且只写一次。 这肯定会减少 I/O 并且性能应该得到改善。

没有足够的声誉来写评论,som 将写为答案。

你没有尝试添加一些时间标记来了解哪些部分花费的时间最多吗?

table2 是否有年份和代码索引? cursor2 查询的解释计划是什么?如果是 - 年份+代码组合平均有多少行? 如果从 table 2 中整体选择的数据量很大 - 那么在 table2 上按年份进行完整 scan/index 范围扫描、分组和散列来执行单个查询可能会更快从 table1 到 table2 的左外连接 like

select a.*, a.rowid, nvl2(c.code, 'Y', 'N') check_col
from table1 a,
(
    select distinct code
    from table2 b
    where b.year = p_year
) c
where a.year = p_year
  and c.code(+) = a.cd