1] Speed DML on Huge number of rows
1.1 Insert throughput Rate
I created
these few commands to get the Insert Rate on my 10.2.0.5 AIX
Power VI / NetApp :
set timing on
drop table adb.table01_1
;
select count(1) from adb.table01 ;
-- create rate direct
create table adb.table01_1
as select * from adb.table01 ;
select blocks , bytes/1024/1024 Sz_MB from dba_segments where owner = 'OWNER' and segment_name = 'AM_TAB_01ION_1' ;
-- insert rate
conventional
delete adb.table01_1 ;
insert into adb.table01_1
select * from adb.table01 ;
select blocks , bytes/1024/1024 Sz_MB from dba_segments where owner = 'OWNER' and segment_name = 'AM_TAB_01ION_1' ;
-- insert rate direct
truncate table adb.table01_1
;
insert /*+ APPEND */ into adb.table01_1
select * from adb.table01 ;
select blocks , bytes/1024/1024 Sz_MB from dba_segments where owner = 'OWNER' and segment_name = 'AM_TAB_01ION_1' ;
drop table adb.table01_1
;
Table dropped.
COUNT(1)
----------
690621
Table created.
Elapsed: 00:00:25:67 -- create rate
Direct = 26 562 rows / sec [ 1.6 Million rows / min ]
BLOCKS SZ_MB
---------- ----------
62464 488
690621 rows deleted.
Elapsed: 00:00:25:87
690621 rows created.
Elapsed: 00:01:03:04 -- insert rate Conventional
= 10 962 rows / sec [ 0.6 Million rows / min ]
BLOCKS SZ_MB
---------- ----------
62848 491
Table truncated.
Elapsed: 00:00:01:41
690621 rows created. -- insert rate Direct
= 27 624 rows / sec [ 1.65 Million rows / min ]
Elapsed: 00:00:24:59
BLOCKS SZ_MB
---------- ----------
62464 488
Table dropped.
Elapsed: 00:00:00:05
Conclusion :
I get a not-Direct DML Insert rate of around 10 K rows per Second ;
and twice more performance when using Direct SQL.
1.2 Delete massive number of rows
First, the
best method, then the case when we can’t shutdown access to the target table.
1.2.1 Faster massive number of rows Delete with INSERT / RENAME
See
following chapter 7] for a complete test-case.
1.2.2 Fast Delete massive number of rows with FORALL loop resumable code
We remove 25
Millions rows,
-
more 2/3rd of a table
-
and can’t afford to stop the access
on the table :
Since we
can’t shutdown the application, I propose this PL/SQL to fast Delete/Commit
every 10 000 Rows. This can be interrupted and resumed without any arm.
We can
follow the state and throughput in V$SESSION.
- Pre-requisite :
select count(code_arr) from TABLE_01
where code_arr
not in (select code_arr
from
t_transaction) and heure <to_date('01/08/2013', 'dd/MM/yyyy') and
id_societe=7 -- 25402611 rows out of
select count(code_arr) from TABLE_01
-- 58394895 rows
- Bulk Delete 25 Millions of rows
$ cat del_table_01_forall.sql
set timing on
DECLARE
l_code_arr dbms_sql.NUMBER_table;
CURSOR c_table_01 is
select code_arr from table_01
where code_arr
not in (select code_arr
from
t_transaction) and heure <to_date('01/08/2013', 'dd/MM/yyyy') and
id_societe=7 ;
-- Main program
/* Count the number of DML during the execution */
v_count NUMBER;
Limit NUMBER;
Start_date date;
BEGIN
execute immediate 'alter
session set cursor_sharing = FORCE' ;
/* Variables initialization */
Limit := 10000;
v_count := 0;
Start_date := sysdate;
OPEN c_table_01
;
LOOP
FETCH c_table_01
BULK COLLECT INTO
l_code_arr LIMIT Limit;
FORALL i in 1 .. l_code_arr.COUNT
DELETE TABLE_01
WHERE code_arr
= l_code_arr(i) ;
COMMIT;
v_count := v_count + 1;
dbms_application_info.set_module( 'num. rows
deleted : '||to_char(v_count*Limit) , null );
dbms_application_info.set_client_info( trunc((v_count*Limit/((sysdate-Start_date)*24*60*60)),2)||' Trx/s' );
EXIT WHEN c_table_01%NOTFOUND;
END LOOP;
CLOSE c_table_01
;
COMMIT;
END;
/
$ nohup sqlplus
system/pswir@TARG_DB @del_table_01_forall.sql &
[1] 29454
select
module , client_info from v$session where sid = 628
module client_info
num. rows
deleted : 220000 2075.47 Trx/s
ü
Conclusion
Throughput
rate was over 2000 DEL / Sec.
Program
Status is shown in V$session :
select module , client_info from v$session where sid = 368
2] Archive those old Data
We are using Datapump, and we want to delete more than 80 % of the
table rows.
2.1 Estimate Space Gain
Using
business rules criteria where date_transaction
< '01/01/2013'
ü
Tables should be analyzed prior to
run this
-- gain
select 'select '''||table_name||''' "TABLE", '''||num_rows||' rows'' "Num_Rows"
, '''||ceil(blocks*8192/1024/1024)||' MB'' "Total Size" ,
count(1) "Archived_Num_Rows" ,
ceil( '||ceil(blocks*8192/1024/1024)||'*(count(1)/'||num_rows||') ) "Gain_MB" from '||owner||'.'||table_name||'
where DATE_TRANSACTION <
''01/01/2013'' UNION '
from dba_tables where owner = 'APP_OWNER' and table_name like 'HISTO%' and num_rows != 0 order by num_rows desc
Remove last
UNION and execute
select 'HISTO_PERS' "TABLE", '50064506 rows' "Num_Rows" , '10845 MB' "Total Size" ,
count(1) "Archived_Num_Rows" ,
ceil( 10845*(count(1)/50064506) ) "Gain_MB" from APP_OWNER.HISTO_PERS
where DATE_TRANSACTION < '01/01/2013' UNION
…
where DATE_TRANSACTION < '01/01/2013' UNION
select 'HISTO_PE_FICHIER' "TABLE", '5 rows' "Num_Rows" , '1 MB' "Total Size" ,
count(1) "Archived_Num_Rows" ,
ceil( 1*(count(1)/5) ) "Gain_MB" from APP_OWNER.HISTO_PE_FICHIER
where DATE_TRANSACTION < '01/01/2013'
TABLE
|
Num_Rows
|
Total Size
|
Archived_Num_Rows
|
Gain_MB
|
HISTO_TAB_01
|
25355054 rows
|
3832 MB
|
15876990
|
2400
|
HISTO_TAB_02
|
15992 rows
|
2 MB
|
10532
|
2
|
HISTO_TAB_03
|
7 rows
|
1 MB
|
4
|
1
|
HISTO_TAB_04
|
10927577 rows
|
1381 MB
|
7314861
|
925
|
HISTO_TAB_05
|
10604 rows
|
2 MB
|
0
|
0
|
HISTO_TAB_06
|
18657 rows
|
8 MB
|
0
|
0
|
HISTO_TAB_07
|
5232314 rows
|
522 MB
|
3165938
|
316
|
HISTO_TAB_08
|
22866424 rows
|
4529 MB
|
14344782
|
2842
|
HISTO_TAB_09
|
2121484 rows
|
217 MB
|
1000101
|
103
|
HISTO_TAB_10
|
2136 rows
|
1 MB
|
992
|
1
|
HISTO_TAB_11
|
10919238 rows
|
1574 MB
|
6898810
|
995
|
HISTO_TAB_12
|
214960 rows
|
25 MB
|
125350
|
15
|
HISTO_TAB_13
|
10102 rows
|
2 MB
|
4606
|
1
|
HISTO_TAB_14
|
50064506 rows
|
10845 MB
|
31747388
|
6878
|
HISTO_TAB_14_TAB_05
|
8653 rows
|
3 MB
|
0
|
0
|
HISTO_TAB_14_TMP
|
58 rows
|
77 MB
|
0
|
0
|
HISTO_TAB_15
|
323248 rows
|
171 MB
|
0
|
0
|
HISTO_TAB_16
|
5 rows
|
1 MB
|
0
|
0
|
HISTO_TAB_17
|
10914958 rows
|
1695 MB
|
6898105
|
1072
|
HISTO_TAB_18
|
214 rows
|
1 MB
|
0
|
0
|
HISTO_TAB_19
|
11218 rows
|
2 MB
|
7904
|
2
|
HISTO_TAB_20
|
16870508 rows
|
2290 MB
|
10315364
|
1401
|
HISTO_TAB_21
|
13689026 rows
|
1829 MB
|
8668626
|
1159
|
HISTO_TAB_22
|
219285 rows
|
21 MB
|
135321
|
13
|
2.2 Export Old Data [ expdp with QUERY clause ]
This is an
INCLUDE :TABLE only export :
$ time expdp system SCHEMAS=APP_OWNER DUMPFILE=<BASE>_DP_DIR:BASE.APP_OWNER.ARCH.HISTO.dp.dmp
LOGFILE=<BASE>_DP_DIR:expdp_BASE.APP_OWNER.ARCH.HISTO.dp.log PARALLEL=2
INCLUDE=TABLE:"\"LIKE 'HISTO_%'\"" QUERY="\"where
date_transaction < '01/01/2013'\""
Import them
if needed to another DB.
2.3 Remove Rows
A method
would be to :
-
Get row count and size
-
Disable Index [oracle disable index
for maintenance ].
-
Delete Rows <
'01/01/2013'
-
Enable row_movement , Shrink ,
Disable row_movement
-
Rebuild Index
-
Gather Stats
-
Get row count and size
A much
faster method, when we can afford downtime :
-
Have a good backup
-
Get row count and size
-
Select rows we want to keep in a
SAVE Table : Direct-(Nologging)-Insert [ CTAS ] >
'31/12/2012'
-
Truncate Original Table
-
Copy back the rows from SAVE to Original
Table
-
Get row count and size
Statistics
on target tables should be up to date ; if necessary, change DBMS_STATS.AUTO_SAMPLE_SIZE
to 100 for small tables
2.3.1 Version where There are NO INDEX on target tables
-- delete
old rows ( were exported before )
-- Have a good backup
-- Get row count and size
-- Select rows we want to keep in a SAVE
Table : Direct-(Nologging)-Insert [ CTAS ]
-- Truncate Original Table
-- Copy back the rows from SAVE to Original
Table
-- Get row count and size After
set serveroutput on
-- exec
DBMS_STATS.GATHER_TABLE_STATS ( 'APP_OWNER','HISTO_ACT',null,DBMS_STATS.AUTO_SAMPLE_SIZE,null,'FOR
ALL INDEXED COLUMNS SIZE AUTO',2,'ALL',TRUE)
-- create
or replace procedure DEL_SHR AS
declare
v_sql VARCHAR2(1024);
v_res VARCHAR2(1024);
v_res_2
VARCHAR2(1024);
v_sz_MB_before integer ;
v_sz_MB_after integer ;
v_redo_MB_before integer ;
v_redo_MB_after integer ;
BEGIN
DBMS_OUTPUT.ENABLE(1000000); -- Clear DBMS_OUTPUT
buffer.
for i in ( select a.owner , a.table_name from dba_tables a
where a.owner='APP_OWNER' and a.table_name like 'HISTO%' and a.num_rows != 0
and not exists ( select '1' from
dba_indexes b where a.owner=b.owner and a.table_name = b.table_name )
order by a.num_rows desc )
loop
-- 1/ info
before
select ceil(value/1024/1024) into v_redo_MB_before from v$mystat natural join v$statname where name = 'redo size' ;
EXECUTE IMMEDIATE 'select ''''||ceil(blocks*8192/1024/1024)||'''' from dba_tables where owner
= '''||i.owner||''' and table_name = '''||i.table_name||''' ' into v_sz_MB_before ;
-- DBMS_OUTPUT.PUT_LINE(' select ''
''||table_name||'' - ''||num_rows||'' rows -
''||ceil(blocks*8192/1024/1024)||'' MB'' from dba_tables where owner = '''||i.owner||'''
and table_name = '''||i.table_name||''' ' ) ;
EXECUTE IMMEDIATE 'select to_char(sysdate, ''YYYY-MM-DD HH24:MI:SS'')||'' Before
''||table_name||'' - ''||num_rows||'' rows -
''||ceil(blocks*8192/1024/1024)||'' MB'' from dba_tables where owner = '''||i.owner||''' and table_name = '''||i.table_name||''' ' into v_res ;
DBMS_OUTPUT.PUT_LINE( v_res ) ;
-- 2/ work
DBMS_OUTPUT.PUT_LINE( ' create table '||i.owner||'.'||i.table_name||'_S as select * from '||i.owner||'.'||i.table_name||' where DATE_TRANSACTION >
''31/12/2012'' ' ) ;
EXECUTE IMMEDIATE 'create table '||i.owner||'.'||i.table_name||'_S as select * from '||i.owner||'.'||i.table_name||' where DATE_TRANSACTION >
''31/12/2012'' ' ;
DBMS_OUTPUT.PUT_LINE( ' truncate table '||i.owner||'.'||i.table_name||' ' ) ;
EXECUTE IMMEDIATE 'truncate table '||i.owner||'.'||i.table_name||' ' ;
DBMS_OUTPUT.PUT_LINE( ' alter table '||i.owner||'.'||i.table_name||' NOLOGGING ' ) ;
EXECUTE IMMEDIATE 'alter table '||i.owner||'.'||i.table_name||' NOLOGGING ' ;
DBMS_OUTPUT.PUT_LINE( ' insert /*+ APPEND */ into '||i.owner||'.'||i.table_name||' select * from '||i.owner||'.'||i.table_name||'_S ' ) ;
EXECUTE IMMEDIATE 'insert /*+ APPEND */ into '||i.owner||'.'||i.table_name||' select * from '||i.owner||'.'||i.table_name||'_S ' ;
commit ;
DBMS_OUTPUT.PUT_LINE( ' DBMS_STATS.GATHER_TABLE_STATS ( '''||i.owner||''','''||i.table_name||''',null,DBMS_STATS.AUTO_SAMPLE_SIZE,null,''FOR
ALL INDEXED COLUMNS SIZE AUTO'',2,''ALL'',TRUE)' ) ;
EXECUTE IMMEDIATE 'BEGIN DBMS_STATS.GATHER_TABLE_STATS ( '''||i.owner||''','''||i.table_name||''',null,DBMS_STATS.AUTO_SAMPLE_SIZE,null,''FOR
ALL INDEXED COLUMNS SIZE AUTO'',2,''ALL'',TRUE); END; ' ;
DBMS_OUTPUT.PUT_LINE( ' alter table '||i.owner||'.'||i.table_name||' LOGGING ' ) ;
EXECUTE IMMEDIATE 'alter table '||i.owner||'.'||i.table_name||' LOGGING ' ;
DBMS_OUTPUT.PUT_LINE( ' drop table '||i.owner||'.'||i.table_name||'_S ' ) ;
EXECUTE IMMEDIATE 'drop table '||i.owner||'.'||i.table_name||'_S ' ;
-- 3/ info
after
EXECUTE IMMEDIATE 'select ''''||ceil(blocks*8192/1024/1024)||'''' from dba_tables where owner
= '''||i.owner||''' and table_name = '''||i.table_name||''' ' into v_sz_MB_after ;
EXECUTE IMMEDIATE 'select to_char(sysdate, ''YYYY-MM-DD HH24:MI:SS'')||'' After
''||table_name||'' - ''||num_rows||'' rows -
''||ceil(blocks*8192/1024/1024)||'' MB'' from dba_tables where owner = '''||i.owner||''' and table_name = '''||i.table_name||''' ' into v_res_2 ;
DBMS_OUTPUT.PUT_LINE( v_res||' '||v_res_2||' GAIN = '||(v_sz_MB_before-v_sz_MB_after)||' MB GAIN_PCT = '||ceil(100*(v_sz_MB_before-v_sz_MB_after)/v_sz_MB_before)||' %' ) ;
select ceil(value/1024/1024) into v_redo_MB_after from v$mystat natural join v$statname where name = 'redo size' ;
DBMS_OUTPUT.PUT_LINE( 'Redo size generated: '||(v_redo_MB_after-v_redo_MB_before)||' MB' ) ;
end loop;
END;
/
Run under
SYSTEM user
2014-12-04
16:53:00 Before HISTO_ACT - 25609416 rows - 3914 MB
create table APP_OWNER.HISTO_ACT_S as select *
from APP_OWNER.HISTO_ACT where DATE_TRANSACTION > '31/12/2012'
truncate table APP_OWNER.HISTO_ACT
alter table APP_OWNER.HISTO_ACT NOLOGGING
insert /*+ APPEND */ into APP_OWNER.HISTO_ACT
select * from APP_OWNER.HISTO_ACT_S
DBMS_STATS.GATHER_TABLE_STATS ( 'APP_OWNER','HISTO_ACT',null,DBMS_STATS.AUTO_SAMPLE_SIZE,null,'FOR
ALL INDEXED COLUMNS SIZE AUTO',2,'ALL',TRUE)
alter table APP_OWNER.HISTO_ACT LOGGING
drop table APP_OWNER.HISTO_ACT_S
2014-12-04
16:53:00 Before HISTO_ACT - 25609416 rows - 3914 MB 2014-12-04 16:56:17 After
HISTO_ACT - 9662204 rows - 1535 MB GAIN = 2379 MB GAIN_PCT = 61 %
Redo size
generated: 1550 MB
PL/SQL
procedure successfully completed.
Note 1 :
Oracle log/undo generated at the session level
-- Total amount of redo
/ undo generated in bytes since the session started:
select 'redo: '||ceil(value/1024/1024)||' MB' from v$mystat natural join v$statname where name = 'redo size'
union
select 'undo: '||ceil(value/1024/1024)||' MB' from v$mystat natural join v$statname where name = 'undo
change vector size';
Note
2 : Direct Insert LOGGING vs. NOLOGGING
LOGGING Redo size
generated 3086 MB
NOLOGGING Redo size
generated: 1550 MB
2.3.2 Other Version that takes of Tables With INDEX
We manage
the index : disable and recreation to speed the whole process.
set serveroutput on
set timing on
set lines 150 pages 5000
DECLARE
TYPE
idxcurtyp IS REF CURSOR;
usr_idxs idxcurtyp ;
TYPE proplist
IS TABLE OF dba_indexes.owner%TYPE;
TYPE idxnlist
IS TABLE OF dba_indexes.index_name%TYPE;
prop
proplist ;
idxn
idxnlist ;
v_sql VARCHAR2(1024);
v_res VARCHAR2(1024);
v_res_2
VARCHAR2(1024);
v_sz_MB_before integer ;
v_sz_MB_after integer ;
v_sz_Idx_MB_before integer ;
v_sz_Idx_MB_after integer ;
v_redo_MB_before integer ;
v_redo_MB_after integer ;
BEGIN
DBMS_OUTPUT.ENABLE(1000000);
-- Clear DBMS_OUTPUT
buffer.
DBMS_OUTPUT.PUT_LINE('START : '||TO_CHAR(SYSDATE,'HH24:MI:SS'));
-- Select tables with Index -> every tables
for i in (
select a.owner , a.table_name
from dba_tables a
where a.owner='APP' and a.table_name
like 'HISTO%' and a.num_rows != 0 and table_name not in ('HISTO_T1')
-- and exists ( select '1' from dba_indexes b where a.owner=b.owner and
a.table_name = b.table_name )
order by a.num_rows desc
)
loop
-- 1/ info before, including Index
DBMS_OUTPUT.PUT_LINE('INFO BEFORE : '||TO_CHAR(SYSDATE,'HH24:MI:SS'));
select ceil(value/1024/1024) into
v_redo_MB_before from v$mystat
natural join v$statname where name = 'redo size' ;
EXECUTE IMMEDIATE 'select
''''||ceil(blocks*8192/1024/1024)||'''' from dba_tables where owner = '''||i.owner||''' and
table_name = '''||i.table_name||''' ' into v_sz_MB_before ;
EXECUTE IMMEDIATE 'select
sum(''''||ceil(blocks*8192/1024/1024)||'''') from dba_indexes a , dba_segments
b where a.owner = '''||i.owner||''' and
table_name = '''||i.table_name||''' and
a.index_name = b.segment_name and a.owner = b.owner ' into v_sz_Idx_MB_before ;
EXECUTE IMMEDIATE 'select
to_char(sysdate, ''YYYY-MM-DD HH24:MI:SS'')||'' Before ''||table_name||'' - ''||num_rows||''
rows - ''||ceil(blocks*8192/1024/1024)||'' MB'' from dba_tables where owner =
'''||i.owner||''' and
table_name = '''||i.table_name||''' ' into v_res ;
-- 2/ work
-- dbms_lock.sleep(20);
DBMS_OUTPUT.PUT_LINE('PREPARE : '||TO_CHAR(SYSDATE,'HH24:MI:SS'));
EXECUTE IMMEDIATE 'create table '||i.owner||'.'||i.table_name||'_S as
select * from '||i.owner||'.'||i.table_name||' where
DATE_TRANSACTION > ''31/12/2014'' ' ;
EXECUTE IMMEDIATE 'truncate table '||i.owner||'.'||i.table_name||' ' ;
EXECUTE IMMEDIATE 'alter
table '||i.owner||'.'||i.table_name||' NOLOGGING
' ;
-- 2b/ index management before
OPEN usr_idxs
for select owner ,
index_name from dba_indexes where owner = ''||i.owner||'' and table_name = ''||i.table_name||'' order by 1 ;
FETCH usr_idxs
BULK COLLECT INTO prop , idxn ;
CLOSE usr_idxs
;
FOR j IN prop.FIRST .. prop.LAST
LOOP
v_sql:= 'ALTER
INDEX '||prop(j)||'.'||idxn(j)||' UNUSABLE';
DBMS_OUTPUT.PUT_LINE( v_sql ) ;
EXECUTE IMMEDIATE v_sql;
END LOOP;
-- index mngt before end
DBMS_OUTPUT.PUT_LINE('INSERT START : '||TO_CHAR(SYSDATE,'HH24:MI:SS'));
EXECUTE IMMEDIATE 'insert /*+ APPEND
*/ into '||i.owner||'.'||i.table_name||' select *
from '||i.owner||'.'||i.table_name||'_S ' ;
commit ;
DBMS_OUTPUT.PUT_LINE('INSERT DONE : '||TO_CHAR(SYSDATE,'HH24:MI:SS'));
-- 2c/ Index management after
DBMS_OUTPUT.PUT_LINE('MNGT AFTER IDX : '||TO_CHAR(SYSDATE,'HH24:MI:SS'));
OPEN usr_idxs
for select owner ,
index_name from dba_indexes where owner = ''||i.owner||'' and table_name = ''||i.table_name||'' order by 1 ;
FETCH usr_idxs
BULK COLLECT INTO prop , idxn ;
CLOSE usr_idxs
;
FOR j IN prop.FIRST .. prop.LAST
LOOP
v_sql:= 'ALTER
INDEX '||prop(j)||'.'||idxn(j)||' REBUILD
ONLINE NOLOGGING';
DBMS_OUTPUT.PUT_LINE( v_sql ) ;
EXECUTE IMMEDIATE v_sql;
END LOOP;
DBMS_OUTPUT.PUT_LINE('MNGT AFTER TABLE : '||TO_CHAR(SYSDATE,'HH24:MI:SS'));
EXECUTE IMMEDIATE 'BEGIN
DBMS_STATS.GATHER_TABLE_STATS ( '''||i.owner||''','''||i.table_name||''',null,DBMS_STATS.AUTO_SAMPLE_SIZE,null,''FOR
ALL INDEXED COLUMNS SIZE AUTO'',2,''ALL'',TRUE); END; ' ;
EXECUTE IMMEDIATE 'alter table '||i.owner||'.'||i.table_name||' LOGGING ' ;
EXECUTE IMMEDIATE 'drop table '||i.owner||'.'||i.table_name||'_S ' ;
-- 3/ info after
DBMS_OUTPUT.PUT_LINE('INFO AFTER : '||TO_CHAR(SYSDATE,'HH24:MI:SS'));
EXECUTE IMMEDIATE 'select
''''||ceil(blocks*8192/1024/1024)||'''' from dba_tables where owner = '''||i.owner||''' and
table_name = '''||i.table_name||''' ' into v_sz_MB_after ;
EXECUTE IMMEDIATE 'select
to_char(sysdate, ''YYYY-MM-DD HH24:MI:SS'')||'' After ''||table_name||'' -
''||num_rows||'' rows - ''||ceil(blocks*8192/1024/1024)||'' MB'' from
dba_tables where owner = '''||i.owner||''' and
table_name = '''||i.table_name||''' ' into v_res_2 ;
DBMS_OUTPUT.PUT_LINE( v_res||' '||v_res_2||' GAIN = '||(v_sz_MB_before-v_sz_MB_after)||' MB GAIN_PCT = '||ceil(100*(v_sz_MB_before-v_sz_MB_after)/v_sz_MB_before)||' %' ) ;
EXECUTE IMMEDIATE 'select sum(''''||ceil(blocks*8192/1024/1024)||'''')
from dba_indexes a , dba_segments b where a.owner = '''||i.owner||''' and
table_name = '''||i.table_name||''' and
a.index_name = b.segment_name and a.owner = b.owner ' into v_sz_Idx_MB_after ;
EXECUTE IMMEDIATE 'select
to_char(sysdate, ''YYYY-MM-DD HH24:MI:SS'')||'' Before ''||table_name||'' -
''||num_rows||'' rows - ''||ceil(blocks*8192/1024/1024)||'' MB'' from
dba_tables where owner = '''||i.owner||''' and
table_name = '''||i.table_name||''' ' into v_res ;
DBMS_OUTPUT.PUT_LINE( 'Idx_Size
Before = '||v_sz_Idx_MB_before||' MB ;
After = '||v_sz_Idx_MB_after||' MB - GAIN
= '||(v_sz_Idx_MB_before-v_sz_Idx_MB_after)||' MB GAIN_PCT = '||ceil(100*(v_sz_Idx_MB_before-v_sz_Idx_MB_after)/v_sz_Idx_MB_before)||' %' ) ;
select ceil(value/1024/1024) into
v_redo_MB_after from v$mystat
natural join v$statname where name = 'redo size' ;
DBMS_OUTPUT.PUT_LINE( 'Redo size
generated: '||(v_redo_MB_after-v_redo_MB_before)||' MB' ) ;
end loop;
END;
/
Run under
SYSTEM user
$ sqlplus system
@delete_histo_2015_idx.sql
SQL*Plus: Release 10.2.0.5.0 - Production on Wed Jan 28 09:02:08 2015
Copyright (c) 1982, 2010, Oracle.
All Rights Reserved.
Enter password:
Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - 64bit
Production
With the Partitioning, OLAP, Data Mining and Real Application Testing
options
ALTER INDEX APP.HP_DTNAI UNUSABLE
ALTER INDEX APP.HP_MATRICULE UNUSABLE
ALTER INDEX APP.HP_CODE UNUSABLE
ALTER INDEX APP.HP_NOMN UNUSABLE
ALTER INDEX APP.HP_PREN UNUSABLE
ALTER INDEX APP.HP_NOM UNUSABLE
ALTER INDEX APP.HP_NUMDEMRSA UNUSABLE
ALTER INDEX APP.HP_NIR UNUSABLE
ALTER INDEX APP.HP_DTNAI REBUILD ONLINE
NOLOGGING
ALTER INDEX APP.HP_MATRICULE REBUILD
ONLINE NOLOGGING
ALTER INDEX APP.HP_CODE REBUILD ONLINE
NOLOGGING
ALTER INDEX APP.HP_NOMN REBUILD ONLINE
NOLOGGING
ALTER INDEX APP.HP_PREN REBUILD ONLINE
NOLOGGING
ALTER INDEX APP.HP_NOM REBUILD ONLINE
NOLOGGING
ALTER INDEX APP.HP_NUMDEMRSA REBUILD
ONLINE NOLOGGING
ALTER INDEX APP.HP_NIR REBUILD ONLINE
NOLOGGING
2015-01-28 09:02:18 Before
HISTO_PERS - 21099061 rows - 4911 MB 2015-01-28 09:48:10 After HISTO_PERS -
10778832 rows - 2515 MB GAIN = 2396 MB GAIN_PCT = 49 %
Idx_Size Before = 3890 MB ; After
= 1989 MB - GAIN = 1901 MB GAIN_PCT = 49 %
Redo size generated: 35281 MB
ALTER INDEX APP_OWNER.HPED_ID_IDX1
UNUSABLE
ALTER INDEX APP_OWNER.HPED_ID_IDX1 REBUILD
ONLINE NOLOGGING
2014-12-08 14:42:19 Before
HISTO_TAB_15 - 325018 rows - 180 MB 2014-12-08 14:42:23 After HISTO_TAB_15 -
65559 rows - 37 MB GAIN = 143 MB GAIN_PCT = 80 %
Idx_Size Before = 9 MB ; After =
2 MB - GAIN = 7 MB GAIN_PCT = 78 %
Redo size generated: 43 MB
PL/SQL procedure successfully completed.
Elapsed: 00:46:32.62
Another
execution :
START : 14:25:55
INFO BEFORE : 14:25:55
PREPARE : 14:25:57
ALTER INDEX APP.TAB1_ID_IDX1 UNUSABLE
INSERT START : 14:26:25
INSERT DONE : 14:26:38
MNGT AFTER IDX : 14:26:38
ALTER INDEX APP.TAB1_ID_IDX1 REBUILD
ONLINE NOLOGGING
MNGT AFTER TABLE : 14:26:46
INFO AFTER : 14:26:58
2016-02-12 14:25:57 Before HISTO_TAB1
- 1216885 rows - 648 MB 2016-02-12
14:26:58 After HISTO_TAB1 -
823069 rows - 447 MB GAIN = 201 MB GAIN_PCT = 32 %
Idx_Size Before = 33 MB ; After =
22 MB - GAIN = 11 MB GAIN_PCT = 34 %
Redo size generated: 449 MB
PL/SQL procedure successfully completed.
START : 14:31:46
INFO BEFORE :
14:31:46
PREPARE : 14:31:48
ALTER INDEX
APP.HP_DTNAI UNUSABLE
…
ALTER INDEX
APP.HP_NIR UNUSABLE
INSERT START :
14:34:49
INSERT DONE :
14:44:45
MNGT AFTER IDX :
14:44:45
ALTER INDEX
APP.HP_DTNAI REBUILD ONLINE NOLOGGING
…
ALTER INDEX
APP.HP_NIR REBUILD ONLINE NOLOGGING
MNGT AFTER TABLE :
14:58:42
INFO AFTER :
15:00:43
2016-02-12
14:31:48 Before HISTO_PERS - 21698308 rows - 4921 MB 2016-02-12 15:00:43 After
HISTO_PERS - 11675711 rows - 2731 MB GAIN = 2190 MB GAIN_PCT = 45 %
Idx_Size
Before = 4009 MB ; After = 2152 MB - GAIN = 1857 MB GAIN_PCT = 47 %
Redo size
generated: 8867 MB