设为首页 收藏本站
查看: 719|回复: 0

[经验分享] ORACLE数据库测试数据插入速度

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2014-4-23 08:53:14 | 显示全部楼层 |阅读模式
一,没有优化的速度:Executed in 69.436 seconds
drop table t purge;
create table t(x int);
/*清空共享池,注意在生产环境中千万不能做这步操作*/
alter system flush shared_pool;
create or replace procedure proc1
as
begin
  for i in 1 .. 100000
    loop
      execute immediate
      'insert into t values('||i||')';
      commit;
    end loop;
end;
/
下面查看下proc1插入100000记录的执行时间
SQL> set timing on;
SQL> exec proc1;

PL/SQL procedure successfully completed

Executed in 69.436 seconds

/*我们可以通过下面的语句查看此存储过程执行的具体步骤*/
select t.sql_text,t.sql_id,t.parse_calls,t.executions from v$sql t where sql_text like '%insert into t values%';
为了方便查看我用PL/SQL DEVELOPER 执行的上面语句,如下图:
SouthEast.jpg
从上面可以看出,每个语句都只是解析了一次,执行了一次,一共解析了10万次,也许你会问你上面只有7136行记录啊,你怎么说是解析了10万次呢。我可以告诉你肯定是解析了10万次,因为我的共享池空间不大,容纳不小10万条信息,根据FIFO 的原理你可以看出,现在我查出来的都是从92000多开始的SQL STATEMENT记录。我们知道这些SQL语句都是相似的没有必要解析10万次,即每一条语句都解析一次。这个PROC1 没有用绑定变量,这就是我们可以优化的地方。我们用绑定变量来重新测试下,下面的PROC2就只用解析一次就可以了,当然速度肯定会提高不少。

二,使用绑定变量优化后的速度:Executed in 26.505 seconds
drop table t purge;
create table t(x int);
/*清空共享池,注意在生产环境中千万不能做这步操作*/
alter system flush shared_pool;

create or replace procedure proc2
as
begin
  for i in 1 .. 100000
    loop
      execute immediate
      'insert into t values(:x)' using i;
      commit;
    end loop;
end;
/
SQL> set timing on;
SQL> exec proc2;

PL/SQL procedure successfully completed

Executed in 26.505 seconds
从上面可以看出,时间基本上减少了一半。
/*我们可以通过下面的语句查看此存储过程执行的具体步骤*/
select t.sql_text,t.sql_id,t.parse_calls,t.executions from v$sql t where sql_text like '%insert into t values%' order by 1;
SouthEast.jpg
从上面的执行情况可以知道,解析了一次,执行了10万次。完全符合我们的猜想,所以速度大大提升了。
execute immediate是一种动态SQL的写法,常用于表名字段名是变量,入参的情况,由于表名不知道,所以不能直接写SQL ,所以要靠动态SQL语句传人表名和字段名参数拼接成SQLSTATEMENT,有execute immediate调用执行。但是我的这个例子完全可以不需要动态的,可以用静态的写好。

三,用静态改写后的速度:Executed in 19.391 seconds
drop table t purge;
create table t(x int);
/*清空共享池,注意在生产环境中千万不能做这步操作*/
alter system flush shared_pool;
create or replace procedure proc3
as
begin
  for i in 1 .. 100000
    loop
      insert into t values(i);
      commit;
    end loop;
end;
/
SQL> set timing on;
SQL> exec proc3;

PL/SQL procedure successfully completed

Executed in 19.391 seconds
SouthEast.jpg
从上面可以看出,proc3也实现了绑定变量,而且动态的特点是执行过程中再解析,而静态的SQL的特点是编译的过程是解析好的,所以上面的PRARSE_CALLS是0。注意这个和上面一个图比较,上面的时PARSE_CALLS 是1,而这个是0,所以静态的少了一个执行的时候的解析过程。
我们可以看出上面的三个PROC都是一条语句就commit一次,我们完全没有必要这样做,我们可以一起提交。如下例: commit的时把log_buffer里的信息通过LGWR写到online redo log里,触发LGWR写10万次,而且我们知道LGWR写的太频繁了。

四,批量提交的速度:Executed in 11.42 seconds
drop table t purge;
create table t(x int);
/*清空共享池,注意在生产环境中千万不能做这步操作*/
alter system flush shared_pool;
create or replace procedure proc4
as
begin
  for i in 1 .. 100000
    loop
      insert into t values(i);
    end loop;
    commit;
end;
/
SQL> set timing on;
SQL> exec proc4;

PL/SQL procedure successfully completed

Executed in 11.42 seconds
可以看出我们用的时间更少了。

五,集合写法的速度:Executed in 0.452 seconds
drop table t purge;
create table t(x int);
/*清空共享池,注意在生产环境中千万不能做这步操作*/
alter system flush shared_pool;
/*下面的语句是由上面的一条一条的插入改为一整批的写进data buffer区里,所以比上面的快,批处理肯定比一个一个的执行快*/
insert into t select rownum from dual connect by level<=100000;
SQL> set timing on;
SQL> insert into t select rownum from dual connect by level<=100000;

100000 rows inserted

Executed in 0.452 seconds
这个是上面的前四种都是一条一条的插入的,我这个集合写法是一整批地写进到DATA BUFFER里,所以比上面的四种情况要快的多。

六,用直接路径写法速度(100万条记录):Executed in 1.514 seconds
/*下面用直接路径的方式来操作,速度会比上面更快,所谓直接路径就是数据不经过database buffer,而是直接写到磁盘,少了一步写到数据缓冲区(database buffer)的动作*/
drop table t purge;
alter system flush shared_pool;
SQL> set timing on;
SQL> create table t as select rownum x from dual connect by level<=1000000;

Table created

Executed in 1.514 seconds
注意此时我插入的记录数十上面的10倍,我是插入100万条记录只用了1.514 seconds.
注意:直接路径的写法比集合写法快事因为,insert into select .... 的方式是将数据首先写到data buffer里,然后再刷到磁盘里。而create as t 的方式跳过了数据缓冲区(data buffer), 直接写进磁盘中,这种方式称之为直接路径读写方式。本来是先到内存,在到磁盘,更改为直接到磁盘,少了一个步骤,所以速度快了。

七,并行写法的速度(100万条记录):Executed in 0.733 seconds
/*并行加直接路径,而且是不写日志的,所以速度比上面的更快*/
drop table t purge;
alter system flush shared_pool;
set timing on;
create table t nologging parallel 64 as select rownum x from dual connect by level<=100000;
SQL> set timing on;
SQL> create table t nologging parallel 4 as select rownum x from dual connect by level<=1000000;

Table created

Executed in 0.733 seconds
我上面只用了parallel 4,如果更多话,还会更快!!!

  • O如何保持读


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-18176-1-1.html 上篇帖子: Oracle 重建索引脚本 下篇帖子: 如何解决ORA-12547: TNS:lost contact错误 数据库
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表