Hi team,
I have a nightmare recently, it comes along with a poor table design of our customer's database: A table named T_PRODUCT_TEST_DATA which has more than 3.6 billion records. What's worse, neither is this table a partitioned table nor has a DATE column.
Since the huge records on this table, the DB runs as slow as my grandma. Finally, my customer realized that something gotta change.
First, they were planed to delete the rows like this:
SQL> set autocommit 1000; -- I doubt this will be effective.
SQL> alter session enable parallel DML;
SQL> delete /*+ parallel(t, 16) */ from T_TEST_PRODUCT_DATA t where TPD_MO in (select MO_NUMBER from T_PM_MO_BASE where MO_CREATE_DATE>=TO_DATE('20150831','YYYYMMDD'));
--about 25,000 out of 50,000 records on T_PM_MO_BASE in this sub query.
SQL> alter table T_TEST_PRODUCT_DATA shrink space cascade;
REBUILT INDEXES.
COMPUTE STATISTICS via DBMS_STATS package.
BTW, they planned to create an historical database center to store the deleted data (with Oracle Golden Gate synchronizing real time data, and OGG filter policy to ignore deleting to ensure the deleted data will remain in historical data center).
As you see, they decide to clear the historical data on this table first, that means about 50% of the records (1.8 billion, more than one-year-old data) will be deleted from this table. And it will consume lots of resource and elapsed for a long time!
I know I should redefinite this table from normal table to partition one. But before that, we have to make this table lose weight, that is to reduce 1.8 billion records on table T_PRODUCT_TEST_DATA. What am I suppose to do?
Lots of discussion about this, I've read this on AskTom
https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:2345591157689 Even so, I think we need your advice still. Cuz it was updated 2 years ago, maybe some new ideas or new solutions. :-)
The advice in that thread is still good. A "create table as select" is likely to be the best approach.
A note on autocommit. As you suspect this probably isn't doing what the authors intended.
From the docs:
The SQL*Plus autocommit feature causes pending changes to be committed after a specified number of successful SQL DML transactions. (A SQL DML transaction is either an UPDATE, INSERT, or DELETE command, or a PL/SQL block.) https://docs.oracle.com/cd/B19306_01/server.102/b14357/ch4.htm So it's not how many rows you process. It's how many statements you run.
For example, the following inserts 99 rows in one statement. Autocommit is set to 10:
SQL> set autocommit 10
SQL> create table t (x int);
Table created.
SQL> insert into t select rownum from dual connect by level < 100;
99 rows created.
SQL> rollback;
Rollback complete.
SQL> select count(*) from t;
COUNT(*)
----------
0
Note that all the rows were rolled back, because it's one transaction!
If we run 12 separate inserts then rollback, the first 10 are autocommitted. Only the last two are undone:
SQL> insert into t values (1);
1 row created.
SQL> /
1 row created.
SQL> /
1 row created.
SQL> /
1 row created.
SQL> /
1 row created.
SQL> /
1 row created.
SQL> /
1 row created.
SQL> /
1 row created.
SQL> /
1 row created.
SQL> /
1 row created.
Commit complete.
SQL> /
1 row created.
SQL> /
1 row created.
SQL> rollback;
Rollback complete.
SQL> select count(*) from t;
COUNT(*)
----------
10