嵌套游标性能调优
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
我有 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