博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Oracle 利用 rowid 提升 update 性能
阅读量:5740 次
发布时间:2019-06-18

本文共 3653 字,大约阅读时间需要 12 分钟。

 

关于ROWID的介绍参考我的Blog

            Oracle Rowid 介绍

           

 

关于大表Update 的一个讨论,参考itpub

           

 

. 在虚拟机上 使用rowid 进行update 测试

            使用rowid 进行update能提高速度,是因为通过rowid 能够迅速的进行定位,不用全表进行扫描。

 

-- 查看表dave 记录数

SYS@dave2(db2)> select count(*) from dave;

  COUNT(*)

----------

   3080115 --300万数据

 

-- 创建测试表dba

SYS@dave2(db2)> create table dba as select * from dave;

Table created.

 

--dave 表去更新DBA

SYS@dave2(db2)>

 

3080115 rows updated.

 

Elapsed: 00:16:12.81 -- 整个更新花了16分钟

 

期间查看session 执行时间:

SQL>select sid,target,time_remaining,elapsed_seconds,message,sql_id from v$session_longops where sid=138;

 

 

select * from v$lock where sid=138;

 

select * from v$session_wait where sid=138;

 

-- 使用rowid 进行更新

  CURSOR cur IS

    SELECT

     a.area_code, b.ROWID ROW_ID

      FROM dave a, dba b

     WHERE a.id = b.id

     ORDER BY b.ROWID;  ---如果表的数据量不是很大,可以不用 order by rowid

  V_COUNTER NUMBER;

BEGIN

  V_COUNTER := 0;

  FOR row IN cur LOOP

    UPDATE dba

       SET prov_code = row.area_code

     WHERE ROWID = row.ROW_ID;

    V_COUNTER := V_COUNTER + 1;

    IF (V_COUNTER >= 1000) THEN

      COMMIT;

      V_COUNTER := 0;

    END IF;

  END LOOP;

  COMMIT;

END;

 

 

PL/SQL procedure successfully completed.

 

Elapsed: 00:14:54.07 -- 执行花了14分钟,速度提高不是很多。

 

            在这个更新中,使用了ORDER BY b.ROWID 进行了排序,每个数据块里面都有多条记录,这样按rowid 进行排序,那么这样每次访问数据块的时候就会相同,就会减小block 在调用的次数,从而提高效率。

 

            因为我这是虚拟机上的测试环境,所以内存分配的并不合适,I/O 也不行。

 

--我们把order by 去掉,在更新看看

  CURSOR cur IS

    SELECT

     a.area_code, b.ROWID ROW_ID

      FROM dave a, dba b

     WHERE a.id = b.id;

  V_COUNTER NUMBER;

BEGIN

  V_COUNTER := 0;

  FOR row IN cur LOOP

    UPDATE dba

       SET prov_code = row.area_code

     WHERE ROWID = row.ROW_ID;

    V_COUNTER := V_COUNTER + 1;

    IF (V_COUNTER >= 1000) THEN

      COMMIT;

      V_COUNTER := 0;

    END IF;

  END LOOP;

  COMMIT;

END;

 

 

PL/SQL procedure successfully completed.

Elapsed: 00:20:24.43

-- 居然用了21分钟,看来对大表还是很有必要进行order by rowid的。

 

. 在测试服务器上测试

            折腾了半天没有折腾出效果来。将数据dump 出来,在imp 到测试服务器,300w的数据,dump 文件有300M

 

--在测试服务器上直接update

SQL> update dba ta set prov_code=(select area_code from dave tb where ta.id=tb.id);

 

update dba ta set prov_code=(select area_code from dave tb where ta.id=tb.id)

       *

ERROR at line 1:

ORA-01013: user requested cancel of current operation

 

Elapsed: 00:20:45.04

 

一直的处理中. 被迫取消。 查看了一下session的状态:

SQL>select sid,target,time_remaining,elapsed_seconds,message,sql_id from v$session_longops where sid=197;

            等了20分钟,才8blocks,要处理到39521blocks,不知道要到那个猴年马月了。 居然比我虚拟机上测试的还慢。

 

-- 在测试服务器上使用rowid + order by

DECLARE

  CURSOR cur IS

    SELECT

     a.area_code, b.ROWID ROW_ID

      FROM dave a, dba b

     WHERE a.id = b.id

     ORDER BY b.ROWID;  ---如果表的数据量不是很大,可以不用 order by rowid

  V_COUNTER NUMBER;

BEGIN

  V_COUNTER := 0;

  FOR row IN cur LOOP

    UPDATE dba

       SET prov_code = row.area_code

     WHERE ROWID = row.ROW_ID;

    V_COUNTER := V_COUNTER + 1;

    IF (V_COUNTER >= 1000) THEN

      COMMIT;

      V_COUNTER := 0;

    END IF;

  END LOOP;

  COMMIT;

END;

 

 

PL/SQL procedure successfully completed.

 

Elapsed: 00:04:45.98

-- 总算看到效果了,4分多钟搞定,如果在生产库上,这个操作应该还会快一点。

 

-- 在测试服务器上使用rowid

 

DECLARE

  CURSOR cur IS

    SELECT

     a.area_code, b.ROWID ROW_ID

      FROM dave a, dba b

     WHERE a.id = b.id;

  V_COUNTER NUMBER;

BEGIN

  V_COUNTER := 0;

  FOR row IN cur LOOP

    UPDATE dba

       SET prov_code = row.area_code

     WHERE ROWID = row.ROW_ID;

    V_COUNTER := V_COUNTER + 1;

    IF (V_COUNTER >= 1000) THEN

      COMMIT;

      V_COUNTER := 0;

    END IF;

  END LOOP;

  COMMIT;

END;

 

 

PL/SQL procedure successfully completed.

Elapsed: 00:09:06.73 -- 花了9分钟

 

         通过以上测试,验证了对于大表的update,除了使用rowid,还需要根据rowid 排序一下。

   

 

 

 

 

 

-------------------------------------------------------------------------------------------------------

Blog http://blog.csdn.net/tianlesoftware

Email: dvd.dba@gmail.com

DBA1 群:62697716();   DBA2 群:62697977()   DBA3 群:62697850()  

DBA 超级群:63306533();  DBA4 群: 83829929  DBA5群: 142216823   

DBA6 群:158654907  聊天 群:40132017   聊天2群:69087192

--加群需要在备注说明Oracle表空间和数据文件的关系,否则拒绝申请

转载于:https://www.cnblogs.com/Hiberniane/archive/2011/06/30/2488405.html

你可能感兴趣的文章
实战:将企业域名解析委派给企业DNS服务器
查看>>
在Lync 2013环境部署Office Web Apps
查看>>
微软大会Ignite,你准备好了么?
查看>>
读书笔记-高标管事 低调管人
查看>>
Master带给世界的思考:是“失控”还是进化
查看>>
用户和开发者不满苹果iCloud问题多多
查看>>
attrs.xml中declare-styleable 详解(用于自定义控件的属性)
查看>>
java.lang.UnsatisfiedLinkError:no dll in java.library.path终极解决之道
查看>>
错误“Unexpected namespace prefix "xmlns" found for tag LinearLayout”的解决方法(转)
查看>>
我的工具:文本转音频文件
查看>>
【许晓笛】从零开始运行EOS系统
查看>>
【跃迁之路】【460天】程序员高效学习方法论探索系列(实验阶段217-2018.05.11)...
查看>>
C++入门读物推荐
查看>>
TiDB 源码阅读系列文章(七)基于规则的优化
查看>>
面试中会遇到的正则题
查看>>
Spring之旅第八站:Spring MVC Spittr舞台的搭建、基本的控制器、请求的输入、表单验证、测试(重点)...
查看>>
数据结构与算法——常用排序算法及其Java实现
查看>>
你所不知的Webpack-多种配置方法
查看>>
React.js 集成 Kotlin Spring Boot 开发 Web 应用实例详解
查看>>
webpack+typescript+threejs+vscode开发
查看>>