请教大虾们,反复执行同一个游标(cursor),每次从表中取出1000条,直到将表中的数据取完;

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了请教大虾们,反复执行同一个游标(cursor),每次从表中取出1000条,直到将表中的数据取完;相关的知识,希望对你有一定的参考价值。

问题描述:现在有一个表有10000W行记录,非常大的表,我知道如果一次性将这10000W放入游标中,循环遍历每一条记录进行处理的话,效率越来越低,最后数据库的undo空间马上用完,所以我想反复执行这个curosr,每次取出100W条进行处理,处理完后再次执行游标再取出100W,直到将这个表中所有数据全部处理完毕,现在想知道如何写这个循环?

我的业务处理规则如下:

定义游标cursor
循环游标cursor
每条进行业务处理后放入数组
最后将数组一次性插入表中

具体结构如下
cursor A is select * from 原始表 A where rownum <=100000 and not exists
(select * from 主键表 B where B.主键 =A.主键 )

LOOP
OPEN A
LOOP
FETCH ....
insert into 主键表 values(主键)
取出每条记录业务处理后放入数组
forall ...inert into 目标表 数组
end loop
close A
end loop

大体就是这样,难点是如果控制循环,如果curosr为空就关闭,就退出,如果不为空,就fetch,处理完100w条后,重新执行curosr再取100w来执行

据我理解,游标并不太占资源。就fetch一条
如果你做处理的时候,怕影响其他用户读数据,你可以分批处理,比如说处理这个月的数据。
如果不影响其他用户,反正是所有的处理都一次完成,只是你的方法比较复杂。
参考技术A while @@fetch_status=0 --判断是否成功获取数据
begin
update table1 set name=name+'1'
where id=@id --进行相应处理(跟据需要填入SQL文)

fetch next from cursor1 into @id,@name --将游标向下移1行
end

close cursor1 --关闭游标
deallocate cursor1

11g新特性之自适应游标共享(Adaptive Cursor Sharing)

自适应游标共享会使包含绑定变量的单个语句拥有多个执行计划,所谓自适应是指执行计划会依据绑定变量的具体值而适配一个最适合该值的执行计划。

 隐藏参数_optimizer_adaptive_cursor_sharing=TRUE 开启或关闭此特性。

首先:游标是否可以被ACS使用,首先游标必须是绑定变量敏感的游标,也就是说最优的执行计划会依赖于绑定变量具体的值。数据库会监控绑定变量敏感的游标,观察是否不同的执行计划会对不同的绑定变量值有好处。

游标在以下两个条件满足的时候会被标记为绑定变量敏感的游标:

1.优化器通过绑定变量窥测去做选择性评估。

2.在绑定变量的列上存在直方图信息。

。。。

对于传入的每个新的游标的具体值,数据库会记录语句执行时的统计信息,语句执行完后,数据库会对比这次执行的统计信息与之前执行的统计信息,如果两者差距很大,则数据库会将该游标标记为 bind-aware 的游标。

当一个游标被标记为 bind-aware的游标后,只要绑定变量的值落入之前收集的绑定变量值与选择率的直方图内,优化器就会重用一个已经存在并且对该绑定变量来说最优的执行计划,如果绑定变量的值没有落入上述直方图内,则会进行硬解析,由此可见,自适应游标共享的好处是既减少了硬解析的次数,对于不同的绑定变量值来说又能找到一个合适它的执行计划。

游标合并:

当优化器创建新的执行计划为 bind-aware的游标后,如果该执行计划和一个已经存在的游标相同的时候,在这种情况下,优化器会合并游标去节省内存空间,数据库会扩大选择性范围去包括新的绑定变量值的选择性。

游标共享相关的性能视图:

  • V$SQL 去检查一个游标是否是 bind-sensitive 以及bind-aware的游标。

  • V$SQL_CS_HISTOGRAM 有绑定变量,选择性,执行次数的直方图。

  • V$SQL_CS_SELECTIVITY 包括绑定变量对选择性范围。

  • V$SQL_CS_STATISTICS summarizes 包括优化器是否将某个游标标记为bind_aware 的统计信息。
SQL> var v_own varchar2(100);
SQL> exec :v_own=‘sys‘;
begin :v_own=‘sys‘; end;
ORA-06550: line 1, column 13:
PLS-00103: Encountered the symbol "=" when expecting one of the following:

   := . ( @ % ; indicator
The symbol ":= was inserted before "=" to continue.
v_own
---------

SQL> exec :v_own:=‘sys‘;
PL/SQL procedure successfully completed
v_own
---------
sys

SQL>select count(distinct 

  

以上是关于请教大虾们,反复执行同一个游标(cursor),每次从表中取出1000条,直到将表中的数据取完;的主要内容,如果未能解决你的问题,请参考以下文章

java读取文件时,InputStream的read(byte[])方法的byte[]的长度不知如何设置,请教大虾们

如何在SQL 2005中实现循环每一行做一定的操作

oracle的游标cursor

11g新特性之自适应游标共享(Adaptive Cursor Sharing)

Oracle游标 CURSOR实例详解

MYSQL 游标学习及使用实例