公司有同事清除大表的时候先truncate,然后drop。问为什么不直接drop,答这样效率高,那真的高吗?其实差不多,先测量下redo,drop 比truncate产生的还少,重点是标黄部分。
产生redo 执行时间
truncate 53k 00: 00: 01.06
drop 26k 00: 00: 00.28
SQL> create table test as select * from dba_objects;
SQL> select value
2 from v$mystat, v$statname
3 where v$mystat.statistic# =v$statname.statistic#
4 and v$statname.name ='redo size';
VALUE
----------
94912
SQL> truncate table test;
Table truncated
SQL> select value
2 from v$mystat, v$statname
3 where v$mystat.statistic# =v$statname.statistic#
4 and v$statname.name ='redo size';
VALUE
----------
149588
SQL> select (149588-94912)/1024 from dual;
(149588-94912)/1024
-------------------
53.39453125
SQL> drop table test purge;
Table dropped
SQL> select value
2 from v$mystat, v$statname
3 where v$mystat.statistic# =v$statname.statistic#
4 and v$statname.name ='redo size';
VALUE
----------
168404
SQL> create table test as select * from dba_objects;
Table created
SQL> select value
2 from v$mystat, v$statname
3 where v$mystat.statistic# =v$statname.statistic#
4 and v$statname.name ='redo size';
VALUE
----------
263320
SQL> drop table test purge;
Table dropped
SQL> select value
2 from v$mystat, v$statname
3 where v$mystat.statistic# =v$statname.statistic#
4 and v$statname.name ='redo size';
VALUE
----------
290364
SQL> select (290364-263320)/1024 from dual;
(290364-263320)/1024
--------------------
26.41015625
用10046跟踪truncate 和drop后台在做什么事情(为了造数据方便,用的不是test表),都是对数据字典的操作。
update语句数量 delete语句数量 insert语句数量
drop 2 45 0
truncate 7 6 1
drop table prod_runlog2 purge 10046产生的结果,剔除select语句:
drop table prod_runlog2 purge --------------------------------------------------------- BEGIN BEGIN IF (xdb.DBMS_XDBZ0.is_hierarchy_enabled_internal(sys.dictionary_obj_owner, sys.dictionary_obj_name, sys.dictionary_obj_owner)) THEN xdb.XDB_PITRIG_PKG.pitrig_truncate(sys.dictionary_obj_owner, sys.dictionary_obj_name); END IF; EXCEPTION WHEN OTHERS THEN null; END; BEGIN IF (xdb.DBMS_XDBZ0.is_hierarchy_enabled_internal(sys.dictionary_obj_owner, sys.dictionary_obj_name, sys.dictionary_obj_owner, xdb.DBMS_XDBZ.IS_ENABLED_RESMETADATA)) THEN xdb.XDB_PITRIG_PKG.pitrig_dropmetadata(sys.dictionary_obj_owner, sys.dictionary_obj_name); END IF; EXCEPTION WHEN OTHERS THEN null; END; END; --------------------------------------------------------- declare stmt varchar2(200); rdf_exception EXCEPTION; pragma exception_init(rdf_exception, -20000); BEGIN if dictionary_obj_type = 'USER' THEN BEGIN EXECUTE IMMEDIATE 'begin ' || 'mdsys.rdf_apis_internal.' || 'notify_drop_user(''' || dictionary_obj_name || '''); ' || 'end;'; EXCEPTION WHEN rdf_exception THEN RAISE; WHEN OTHERS THEN NULL; END; end if; end; --------------------------------------------------------- delete from object_usage where obj# in (select a.obj# from object_usage a, ind$ b where a.obj# = b.obj# and b.bo# = :1) --------------------------------------------------------- delete from sys.cache_stats_1$ where dataobj# = :1 --------------------------------------------------------- delete com$ where obj#=:1 --------------------------------------------------------- delete from hist_head$ where obj# = :1 --------------------------------------------------------- delete from dependency$ where d_obj#=:1 --------------------------------------------------------- delete from source$ where obj#=:1 --------------------------------------------------------- DELETE FROM sys.sumdelta$ sd WHERE sd.tableobj# = :1 --------------------------------------------------------- DELETE FROM sys.sumpartlog$ sp WHERE sp.bo# = :1 --------------------------------------------------------- DELETE FROM sys.snap_loadertime$ sd WHERE sd.tableobj# = :1 --------------------------------------------------------- BEGIN aw_drop_proc(ora_dict_obj_type, ora_dict_obj_name, ora_dict_obj_owner) ; END; --------------------------------------------------------- declare stmt varchar2(200); BEGIN if dictionary_obj_type = 'USER' THEN stmt := 'DELETE FROM SDO_GEOM_METADATA_TABLE ' || ' WHERE ''"''||SDO_OWNER||''"'' = ''"' || dictionary_obj_name || '"'' '; EXECUTE IMMEDIATE stmt; stmt := 'DELETE FROM SDO_MAPS_TABLE ' || ' WHERE ''"''||SDO_OWNER||''"'' = ''"' || dictionary_obj_name || '"'' '; EXECUTE IMMEDIATE stmt; stmt := 'DELETE FROM SDO_STYLES_TABLE ' || ' WHERE ''"''||SDO_OWNER||''"'' = ''"' || dictionary_obj_name || '"'' '; EXECUTE IMMEDIATE stmt; stmt := 'DELETE FROM SDO_THEMES_TABLE ' || ' WHERE ''"''||SDO_OWNER||''"'' = ''"' || dictionary_obj_name || '"'' '; EXECUTE IMMEDIATE stmt; stmt := 'DELETE FROM SDO_LRS_METADATA_TABLE ' || ' WHERE ''"''||SDO_OWNER||''"'' = ''"' || dictionary_obj_name || '"'' '; EXECUTE IMMEDIATE stmt; stmt := 'DELETE FROM SDO_TOPO_METADATA_TABLE ' || ' WHERE ''"''||SDO_OWNER||''"'' = ''"' || dictionary_obj_name || '"'' '; EXECUTE IMMEDIATE stmt; end if; end; --------------------------------------------------------- DECLARE type vcurType is REF CURSOR; vcur vcurType; stmt VARCHAR2(1000); stm2 VARCHAR2(200); rdt VARCHAR2(80); rsid number; cnt number; BEGIN IF dictionary_obj_type = 'USER' THEN stmt := 'DELETE FROM SDO_GEOR_SYSDATA_TABLE WHERE SDO_OWNER = :name'; EXECUTE IMMEDIATE stmt using dictionary_obj_name; ELSIF dictionary_obj_type = 'TABLE' AND dictionary_obj_owner <> 'MDSYS' AND dictionary_obj_name <> 'SDO_GEOR_SYSDATA_TABLE' THEN stmt := 'SELECT COUNT(*) FROM SDO_GEOR_SYSDATA_TABLE ' || ' WHERE SDO_OWNER = :1 AND GEORASTER_TABLE_NAME = :2'; EXECUTE IMMEDIATE stmt INTO cnt USING dictionary_obj_owner, dictionary_obj_name; IF cnt > 0 THEN stmt := 'SELECT RDT_TABLE_NAME, RASTER_ID FROM SDO_GEOR_SYSDATA_TABLE' || ' WHERE SDO_OWNER = :1 AND GEORASTER_TABLE_NAME = :2'; open vcur for stmt using dictionary_obj_owner, dictionary_obj_name; loop fetch vcur into rdt, rsid; exit when vcur%NOTFOUND; if instr(rdt, '.') = 0 then rdt := dictionary_obj_owner || '.' || rdt; end if; stm2 := 'DELETE FROM ' || rdt || ' WHERE rasterid=:1'; begin execute immediate stm2 using rsid; exception when others then if SQLCODE <> -942 then raise; end if; end; end loop; stmt := 'DELETE FROM SDO_GEOR_SYSDATA_TABLE ' || ' WHERE SDO_OWNER = :name AND GEORASTER_TABLE_NAME = :2'; EXECUTE IMMEDIATE stmt USING dictionary_obj_owner, dictionary_obj_name; END IF; END IF; END; --------------------------------------------------------- DECLARE stmt VARCHAR2(256); BEGIN stmt := 'DELETE FROM SDO_NETWORK_METADATA_TABLE WHERE SDO_OWNER = :name'; IF dictionary_obj_type = 'USER' THEN EXECUTE IMMEDIATE stmt using NLS_UPPER(dictionary_obj_name); END IF; END ; --------------------------------------------------------- DECLARE stmt VARCHAR2(256); BEGIN stmt := 'DELETE FROM SDO_NETWORK_CONSTRAINTS WHERE SDO_OWNER = :name'; IF dictionary_obj_type = 'USER' THEN EXECUTE IMMEDIATE stmt using NLS_UPPER(dictionary_obj_name); END IF; END ; --------------------------------------------------------- DECLARE stmt VARCHAR2(256); BEGIN stmt := 'DELETE FROM SDO_NETWORK_USER_DATA WHERE SDO_OWNER = :name'; IF dictionary_obj_type = 'USER' THEN EXECUTE IMMEDIATE stmt using NLS_UPPER(dictionary_obj_name); END IF; END ; --------------------------------------------------------- delete from idl_ub1$ where obj#=:1 and part=:2 --------------------------------------------------------- delete from idl_char$ where obj#=:1 and part=:2 --------------------------------------------------------- delete from idl_ub2$ where obj#=:1 and part=:2 --------------------------------------------------------- delete from idl_sb4$ where obj#=:1 and part=:2 --------------------------------------------------------- delete from ncomp_dll$ where obj#=:1 returning dllname into :2 --------------------------------------------------------- delete from objauth$ where obj#=:1 --------------------------------------------------------- delete from col$ where obj#=:1 --------------------------------------------------------- delete from icol$ where bo#=:1 --------------------------------------------------------- delete from icoldep$ where obj# in (select obj# from ind$ where bo#=:1) --------------------------------------------------------- delete from jijoin$ where obj# in ( select obj# from jijoin$ where tab1obj# = :1 or tab2obj# = :1) --------------------------------------------------------- delete from jirefreshsql$ where iobj# in ( select iobj# from jirefreshsql$ where tobj# = :1) --------------------------------------------------------- delete from ccol$ where obj#=:1 --------------------------------------------------------- delete from ind$ where bo#=:1 --------------------------------------------------------- delete from cdef$ where obj#=:1 --------------------------------------------------------- delete from tab$ where obj#=:1 --------------------------------------------------------- delete coltype$ where obj#=:1 --------------------------------------------------------- delete from subcoltype$ where obj#=:1 --------------------------------------------------------- delete ntab$ where obj#=:1 --------------------------------------------------------- delete lob$ where obj#=:1 --------------------------------------------------------- select o.name from obj$ o, refcon$ r where o.oid$ = r.expctoid and r.obj# = :1 --------------------------------------------------------- delete refcon$ where obj#=:1 --------------------------------------------------------- delete from opqtype$ where obj#=:1 --------------------------------------------------------- update seg$ set type#=:4,blocks=:5,extents=:6,minexts=:7,maxexts=:8,extsize= :9,extpct=:10,user#=:11,iniexts=:12,lists=decode(:13, 65535, NULL, :13), groups=decode(:14, 65535, NULL, :14), cachehint=:15, hwmincr=:16, spare1= DECODE(:17,0,NULL,:17),scanhint=:18 where ts#=:1 and file#=:2 and block#=:3 --------------------------------------------------------- delete from obj$ where obj# = :1 --------------------------------------------------------- delete from con$ where owner#=:1 and name=:2 --------------------------------------------------------- update tsq$ set blocks=:3,maxblocks=:4,grantor#=:5,priv1=:6,priv2=:7,priv3=:8 where ts#=:1 and user#=:2 --------------------------------------------------------- delete from seg$ where ts#=:1 and file#=:2 and block#=:3 ---------------------------------------------------------
truncate table prod_runlog2 10046产生的结果,剔除select语句:
truncate table --------------------------------------------------------- truncate table prod_runlog1 BEGIN BEGIN IF (xdb.DBMS_XDBZ0.is_hierarchy_enabled_internal(sys.dictionary_obj_owner, sys.dictionary_obj_name, sys.dictionary_obj_owner)) THEN xdb.XDB_PITRIG_PKG.pitrig_truncate(sys.dictionary_obj_owner, sys.dictionary_obj_name); END IF; EXCEPTION WHEN OTHERS THEN null; END; BEGIN IF (xdb.DBMS_XDBZ0.is_hierarchy_enabled_internal(sys.dictionary_obj_owner, sys.dictionary_obj_name, sys.dictionary_obj_owner, xdb.DBMS_XDBZ.IS_ENABLED_RESMETADATA)) THEN xdb.XDB_PITRIG_PKG.pitrig_dropmetadata(sys.dictionary_obj_owner, sys.dictionary_obj_name); END IF; EXCEPTION WHEN OTHERS THEN null; END; END; --------------------------------------------------------- update obj$ set obj#=:6,type#=:7,ctime=:8,mtime=:9,stime=:10,status=:11, dataobj#=:13,flags=:14,oid$=:15,spare1=:16, spare2=:17 where owner#=:1 and name=:2 and namespace=:3 and(remoteowner=:4 or remoteowner is null and :4 is null)and(linkname=:5 or linkname is null and :5 is null) and(subname=:12 or subname is null and :12 is null) --------------------------------------------------------- update sys.mon_mods$ set inserts = inserts + :ins, updates = updates + :upd, deletes = deletes + :del, flags = (decode(bitand(flags, :flag), :flag, flags, flags + :flag)), drop_segments = drop_segments + :dropseg, timestamp = :time where obj# = :objn --------------------------------------------------------- insert into sys.mon_mods$ values (:1, :2, :3, :4, :5, :6, :7) --------------------------------------------------------- delete from tab_stats$ where obj#=:1 --------------------------------------------------------- update tab$ set ts#=:2,file#=:3,block#=:4,bobj#=decode(:5,0,null,:5),tab#= decode(:6,0,null,:6),intcols=:7,kernelcols=:8,clucols=decode(:9,0,null,:9), audit$=:10,flags=:11,pctfree$=:12,pctused$=:13,initrans=:14,maxtrans=:15, rowcnt=:16,blkcnt=:17,empcnt=:18,avgspc=:19,chncnt=:20,avgrln=:21, analyzetime=:22,samplesize=:23,cols=:24,property=:25,degree=decode(:26,1, null,:26),instances=decode(:27,1,null,:27),dataobj#=:28,avgspc_flb=:29, flbcnt=:30,trigflag=:31,spare1=:32,spare2=decode(:33,0,null,:33),spare4=:34, spare6=:35 where obj#=:1 --------------------------------------------------------- update seg$ set type#=:4,blocks=:5,extents=:6,minexts=:7,maxexts=:8,extsize= :9,extpct=:10,user#=:11,iniexts=:12,lists=decode(:13, 65535, NULL, :13), groups=decode(:14, 65535, NULL, :14), cachehint=:15, hwmincr=:16, spare1= DECODE(:17,0,NULL,:17),scanhint=:18 where ts#=:1 and file#=:2 and block#=:3 --------------------------------------------------------- update tsq$ set blocks=:3,maxblocks=:4,grantor#=:5,priv1=:6,priv2=:7,priv3=:8 where ts#=:1 and user#=:2 --------------------------------------------------------- DECLARE type vcurType is REF CURSOR; vcur vcurType; stmt VARCHAR2(1000); stm2 VARCHAR2(250); rdt VARCHAR2(80); rsid number; cnt number; m_id number; BEGIN IF dictionary_obj_type <> 'TABLE' THEN return; END IF; stmt := 'SELECT COUNT(*) FROM SDO_GEOR_SYSDATA_TABLE ' || ' WHERE SDO_OWNER = :1 AND GEORASTER_TABLE_NAME = :2'; EXECUTE IMMEDIATE stmt INTO cnt USING dictionary_obj_owner, dictionary_obj_name; IF cnt > 0 THEN stmt := 'SELECT RDT_TABLE_NAME, RASTER_ID FROM SDO_GEOR_SYSDATA_TABLE' || ' WHERE SDO_OWNER = :1 AND GEORASTER_TABLE_NAME = :2'; open vcur for stmt using dictionary_obj_owner, dictionary_obj_name; loop fetch vcur into rdt, rsid; exit when vcur%NOTFOUND; if instr(rdt, '.') = 0 then rdt := dictionary_obj_owner || '.' || rdt; end if; stm2 := 'DELETE FROM ' || rdt || ' WHERE rasterid=:1'; begin execute immediate stm2 using rsid; exception when others then if SQLCODE <> -942 then raise; end if; end; end loop; stmt := 'DELETE FROM SDO_GEOR_SYSDATA_TABLE ' || ' WHERE SDO_OWNER = :name AND GEORASTER_TABLE_NAME = :2'; EXECUTE IMMEDIATE stmt USING dictionary_obj_owner, dictionary_obj_name; END IF; stmt := 'SELECT COUNT(*) FROM ALL_TABLES ' || ' WHERE OWNER = ''MDSYS'' AND TABLE_NAME = ''RDF_MODEL$'' '; EXECUTE IMMEDIATE stmt INTO cnt; if (cnt = 1) then begin cnt := 0; stmt := 'SELECT count(*) FROM MDSYS.RDF_MODEL$ ' || ' WHERE OWNER = :1 AND TABLE_NAME = :2'; EXECUTE IMMEDIATE stmt INTO cnt USING dictionary_obj_owner, dictionary_obj_name; if (cnt > 0) then stmt := 'SELECT model_id FROM MDSYS.RDF_MODEL$ ' || ' WHERE OWNER = :1 AND TABLE_NAME = :2'; EXECUTE IMMEDIATE stmt INTO m_id USING dictionary_obj_owner, dictionary_obj_name; stmt := ' DELETE MDSYS.RDF_LINK$ WHERE model_id = '||to_char(m_id) ; EXECUTE IMMEDIATE stmt; end if; exception when others then NULL; end; end if; END; ---------------------------------------------------------