oracle的數據處理之insert,delete,truncate partition,bulk collect into

個人測試方法
測試環境t4400+2G+5400轉/秒硬盤。表大小248MB,1997760條數據。

創建一個基表:sql

create table a_object as
select object_name,object_type,created,rownum+49944 id  from dba_objects
alter table a_object add primary key (id);

創建一個影子表:
create table b_object as select * from a_Object
1 查詢速度比較
bash

a_object
SQL> select count(*) from a_object;
COUNT(*)
----------
499440
Executed in 0.219 seconds
SQL> select  count(*) from b_object;
COUNT(*)
----------
499440
Executed in 0.766 seconds

這個容易看出,a_object有主鍵,快,沒啥好解釋的
app

SQL> alter system flush buffer_cache;
SQL> alter system flush shared_pool;
SQL> select count(*) from b_Object a;
COUNT(*)
----------
1997760
Executed in 4.344 seconds
SQL> select /*+parallel(a,2)*/ count(*) from b_object a;
COUNT(*)
----------
1997760
Executed in 2 seconds

加parallel仍是有點用,若是cpu更多,可能會更快。
2 插入
a_Object:less

insert into a_object
select object_name,object_type,created,rownum+998880 id  from b_object

59秒ide

b_object:oop

insert into b_object
select object_name,object_type,created,rownum+998880 id  from b_object

25秒
有索引確定慢些,這個沒什麼好解釋的
測試

insert /*+append*/ into a_objectselect
 object_name,object_type,created,rownum+1997760 id  from b_object

107.531秒

fetch

insert /*+parallel(a,2)*/ into a_object a
select object_name,object_type,created,rownum+1997760 id  from b_object

175.172秒,還慢些

ui

insert into a_object a
select object_name,object_type,created,rownum+1997760 id  from b_object

197.125秒,最慢

spa

insert /*+append parallel(a,2)*/into a_object a
select object_name,object_type,created,rownum+1997760 id  from b_object

193.703秒,看樣子parallel對錶的insert 用處不大,用處最大的是append
alter table a_object  nologging 讓表不記日誌,再

insert /*+append*/  into b_object
select object_name,object_type,created,rownum+1997760 id  from
 b_object

57.688秒最快

bulk collect insert into
declaretype t_object is table of b_object.object_name%type index by binary_integer;
type t_type is table of b_object.object_type%type index by binary_integer;
type t_created is table of b_object.created%type index by binary_integer;
type t_Id is table of b_object.id%type index by binary_integer;
objects t_object ;
types t_type ;
createds t_created ;
ids t_id ;
cursor cur is select * from b_object;
begin
open cur;
loop
fetch cur bulk collect into objects,types,createds,ids limit 5000;
for i in 1..ids.count loop
insert into a_object values (objects(i),types(i),createds(i),ids(i)+1997760);
end loop;
exit when cur%notfound;
end loop;
close cur;
end;

468.888秒。這個確定最慢。
改寫

declare
type object_type is record
(
object_name b_object.object_name%type,
object_type b_object.object_type%type,
created     b_object.created%type,
id          b_object.id%type
);
type t_object_type is  table of object_type;
objects t_object_type ;
v_counter   PLS_INTEGER := 0;
cursor cur is select object_name,object_type,created,id+1997760 id from b_object;
begin
open cur;
loop
fetch cur bulk collect into objects limit 10000;
for i in 1..objects.last loop
insert into a_object values objects(i);
end loop;
v_counter:=v_counter+1;
exit when cur%notfound;
end loop;
dbms_output.put_line('counter is :'||v_counter);
close cur;
end;

363秒。仍是很慢,用forall改寫,

 declare 
        type object_type is record
        (
        object_name b_object.object_name%type,
        object_type b_object.object_type%type,
        created     b_object.created%type,
        id          b_object.id%type
        );
        type t_object_type is  table of object_type;     
        objects t_object_type ;
        v_counter   PLS_INTEGER := 0;  
        cursor cur is select object_name,object_type,created,id+1997760 id from b_object;
        begin
          open cur;
loop 
fetch cur 
bulk collect 
into
 objects 
limit 
10000;
            forall i in 1..objects.last 
insert into 
a_object values objects(i);
              v_counter:=v_counter+1;
             exit when cur%notfound;
end loop;
           dbms_output.put_line('counter is :'||v_counter);
close cur;
end;

快了很多,131秒。這個速度比較理想。

  declare 
        type object_type is record
        (
        object_name b_object.object_name%type,
        object_type b_object.object_type%type,
        created     b_object.created%type,
        id          b_object.id%type
        );
        type t_object_type is  table of object_type;     
        objects t_object_type ;
        v_counter   PLS_INTEGER := 0;  
        cursor cur is select object_name,object_type,created,id+1997760 id from b_object;
        begin
          open cur;
loop 
            fetch 
cur bulk collect 
into 
objects 
limit
 10000;
            exit when objects.count=0;
             v_counter:=v_counter+1;
             forall
 i in 1..objects.last 
             insert into 
a_object values objects(i);
             end loop;
           dbms_output.put_line('counter is :'||v_counter);
           close cur;
 end;

這個有點離譜,竟然變成84.6秒,應當是剛纔沒刷shared_pool和buffer_cache所致。
 

alter system flush shared_pool;
alter system flush buffer_cache;


注意,以上兩條僅限測試環境。
刷新後:158.875秒
。。。。繼續更改:

  declare 
        type object_type is record
        (
        object_name b_object.object_name%type,
        object_type b_object.object_type%type,
        created     b_object.created%type,
        id          b_object.id%type
        );
        type t_object_type is  table of object_type;     
        objects t_object_type ;
        v_counter   PLS_INTEGER := 0;  
        cursor cur is select object_name,object_type,created,id+1997760 id from b_object;
 begin
open 
cur;
  loop 
fetch
 cur bulk collect into objects 
limit
 10000;
            exit 
when
 objects.count=0;
             v_counter:=v_counter+1;
forall
 i 
in
 1..objects.last 
insert 
/* +append */ 
 into a_object values objects(i);
  end loop;
           dbms_output.put_line('counter is :'||v_counter);
close
 cur;
 end;


加append;134.672秒。固然這個僅僅是測試,顯得有點冗餘,但當有條件時,寫比較複雜的的轉換,又不是對單表操做時儘可能用bulk collect  forall吧。

最後測一下merge into

merge into scott.p_object a
using  (select object_name,object_type,created,id+1997760 ID from b_object) b  oN (a.id=b.id)
--when matched then
-- NULL;
-- update set a.ename=b.ename
when not matched then
insert values(b.object_name,b.object_type,b.created,b.id)

其實不測也應當能夠斷定,這個不咋地,10秒都沒出結果。。。。

 

如下開始測刪除,從傻瓜式刪除開始:
delete from a_Object where id>1997760
--377.14秒
alter table a_object drop constraints SYS_C005373
刪除索引後再試,結果慘不忍睹。
建分區表:

create table SCOTT.P_OBJECT
(
object_name VARCHAR2(128),
object_type VARCHAR2(19),
created     DATE,
id          NUMBER
)
partitionby range (id) (
partition p1 values less than (1997760),
partition p2 values less than (3995520)
);
alter table p_object nologging;
insert /*+append*/ into  p_object  select * from a_object;
alter table p_object truncate partition p2;

因爲索引失效還需重建索引

alter index SYS_C005787 rebuild nologging;


insert into 花時248秒,truncate 分區1秒,重建索引15秒。
上一步也能夠用再線重定義分區表作。。
順便 提一下這裏的統計信息

begin
dbms_stats.gather_table_stats('SCOTT','P_OBJECT', cascade =>true);
end;


 用這個收集後不許了。

select num_rows,t.EMPTY_BLOCKS,t.BLOCKS*8/1024,t.LAST_ANALYZED,t.logging from all_tables t where table_name='P_OBJECT' and owner='SCOTT'
select table_name,partition_position,num_rows,blocks*8/1024,sample_size,last_analyzed,high_value from all_tab_partitions where table_owner='SCOTT'
select i.INDEX_NAME,i.table_name,i.num_rows,i.blevel,i.logging,i.DISTINCT_KEYS,i.LAST_ANALYZED from all_indexes i where table_name='P_OBJECT'
相關文章
相關標籤/搜索