個人測試方法
測試環境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'