Sql 嵌套游标性能调整

Sql 嵌套游标性能调整,sql,oracle,performance,plsql,cursor,Sql,Oracle,Performance,Plsql,Cursor,我有两个游标,一个用于从包含50列和10000+数据的表中获取记录,另一个用于检查另一个大表(200万数据)中是否存在特定列。我应该将游标1中的所有记录写入一个文件,保存一年,如果游标2中存在该列,那么我应该将错误消息打印为存在,而不是删除它们。如果它不存在,那么我应该删除该行,并将其写入与已删除记录相同的文件和消息中。 我使用了一个嵌套游标,性能太差了,因为它每次都处理游标1和游标2之间的每一行 CURSOR cursor1 IS

我有两个游标,一个用于从包含50列和10000+数据的表中获取记录,另一个用于检查另一个大表(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_表中的行存储到您的文件中。如果没有,请将它们保留在
LOG\u表中

utl\u文件中。将行放入循环将产生开销。请尝试将行追加到lv\u msg,直到字符串长度为32767字节,然后只写入一次。
这肯定会减少I/O,性能应该得到提高。

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

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

表2是否有按年份和代码列出的索引?cursor2查询的解释计划是什么?如果是-年+代码组合的平均行数是多少? 如果从表2中整体选择的数据量很大,那么使用表2中的完整扫描/索引范围按年扫描、从表1到表2的分组和散列左外部联接进行单个查询可能会更快

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

就像把它存储在临时表中一样。恐怕我不能这么做。我应该附加UTLYFIL.PUTYLIN而不是写它吗?你不想在中间记录一个LVIMSG。继续用新行(chr(10))附加到lv_msg,当长度刚好小于32767时,写入文件并将lv_msg重置为null。我尝试了这个方法,性能只提高了几分钟。感谢you@Doranaut我尝试了单查询,性能比以前好多了。感谢you@Doranaut-当我尝试向表1A添加更多条件时,它会一直运行。我只是在加入之前使用和添加conditions@arsha附加条件可能会改变执行计划。查询文本及其执行计划至少需要说明任何内容。