日期:2014-05-16  浏览次数:20469 次

构建百万千万级表的多种方法及其性能对比分析
前两个实验是前一段自己做的。后面的实验是一本书上的。
实验环境:虚拟机,LINUX+ORACLE 11G
说明:每个实验完成后,需要及时删除表,以便进行下一个实验。 我这里节约篇幅,省略了。
删除重新开始下一个实验
drop table test1 purge;
drop table test2 purge;
truncate table test3;

drop table test3 purge;

清除缓冲区和共享池

alter system flush buffer_cache;
alter system flush shared_pool; --这里只清共享池就可以。

关于硬解析与软解析-来自网络:

一次硬解析,多次软解析,Session_cache_cursor设置为0,最容易发生,软解析的代价是,每次要在library cache中定位游标。

一次硬解析,多次软解析,Session_cache_cursor设置为非空值,PGA中保留了指向library cache的指针,直接定位子游标。

一次解析,多次执行,保持游标打开(pin住内存堆),没有定位自由表的过程,容易造成打开游标数过多,要记得代码的最后关闭游标。

 select t.sql_text, t.sql_id,t.PARSE_CALLS, t.EXECUTIONS  from v$sql t  where sql_text like '%insert into test1 %' and rownum <10;

方法一:使用布尔积,速度很快。

BYS@ bys001>create table test1 as select rownum a from dual connect by rownum<1001;
BYS@ bys001>alter system flush shared_pool;
BYS@ bys001>create table test3 as select a.* from test1 a,test1 b;
Table created.

Elapsed: 00:00:01.63
BYS@ bys001>select count(*) from test3;
  COUNT(*)
----------
   1000000
##########################################################################

方法二:利用自查询插入,速度比较慢。

BYS@ bys001>create table test1 as select rownum a from dual connect by rownum<10001;
Table created.
Elapsed: 00:00:00.25
begin
for i in 1 .. 10 loop
insert into test1 select * from test1;
end loop;
commit;
end;
/

PL/SQL procedure successfully completed.
Elapsed: 00:00:43.62

BYS@ bys001>select count(*) from test1;
  COUNT(*)
----------
   1024000
Elapsed: 00:00:00.02

插入速度是每秒两万多条
BYS@ bys001>select 1024000/43 from dual;
1024000/43
----------
23813.9535
19:34:16 SQL>  select t.sql_text, t.sql_id,t.PARSE_CALLS, t.EXECUTIONS
           2    from v$sql t
           3   where sql_text like '%INSERT INTO TEST1%' and rownum <10;          

SQL_TEXT                       SQL_ID        PARSE_CALLS EXECUTIONS
------------------------------ ------------- ----------- ----------

INSERT INTO TEST1 SELECT * FRO cwjfx8x2zfvq1           1         10

批量提交节约了每次提交时 commit耗费的时间。
但是在大DML事务时,要注意延迟块清除可能引起的ORA-01555错误。在此不多说这个问题。
########################################################

方法三:创建存储过程,未使用绑定变量。速度很慢

这里只插入100万条数据来测试,因为插入1000万条数据需要时间太长(我虚拟机是一个小时左右)。

create or replace procedure proc_test1
as
begin
for i in 1 .. 1000000
loop
execute immediate
'insert into test1 values ( '||i||')';
commit;
end loop;
end;
/

Procedure created.
BYS@ bys001>create table test1(a number);
BYS@ bys001>alter system flush shared_pool;
BYS@ bys001>exec proc_test1;

PL/SQL procedure successfully completed.

Elapsed: 00:13:03.43

BYS@ bys001>select count(*) from test1;
  COUNT(*)
----------
   1000000

每秒插入一千多条数据,数据条数除所用时间
BYS@ bys001>select 1000000/13/60 from dual;
1000000/13/60
-------------
   1282.05128

查询共享池中有缓存,可以看到每个语句都是只解析一次,执行一次。
整个存储过程解析了100万次,所以耗时很长。
SQL>  select t.sql_text, t.sql_id,t.PARSE_CALLS, t.EXECUTIONS
  2