To delete large number of rows, for instance rows with date until 2010, you can issue this simple statement.
SQL> DELETE FROM T WHERE C<DATE '2011-01-01'; 1'000'000'000 rows deleted Elapsed: 23:45:22.01 SQL> commit;
This is perfectly fine. The table remains online, other users are not much affected (maybe they will not even notice the lower IO performance).
It will generate quite a lot of UNDO, and you will need enough space for archivelog and a large undo tablespace and a large undo retention setting (to prevent ORA-01555 snapshot too old).
If your table is like 100G big, you do it during week-end, you have 500Gb Undo and 250G free space in your archive destination, you will be fine. Well. Maybe.
There are workarounds where you create a new table then rename etc… but this is not the scope of this post and you will need to validate your index / foreign keys / online strategy with the application guys.
Another way to decrease runtime pro statement and undo requirement pro statement (but increase overall elapsed time) is to divided it chunks, for instance to delete 100’000’000 rows each night during 10 days.
SQL> DELETE FROM T WHERE C<DATE '2011-01-01' AND ROWNUM<=100000000; 100'000'000 rows deleted Elapsed: 04:11:15.31 SQL> commit;
Or if you want to delete in much smaller chunks to accomodate your tiny undo tablespace, you could try
BEGIN LOOP DELETE FROM T WHERE C<DATE '2011-01-01' AND ROWNUM <= 1000; EXIT WHEN SQL%ROWCOUNT = 0; COMMIT; END LOOP; END; /
This will run longer than a single transaction, but it is quite usefull if your undo tablespace is too small. Also if you abort it (CTRL-C or kill session), you will not lose all progresses (but you lose on integrity/atomicity) and your KILL SESSION will not last for ever. With a single transaction, your session may be marked as killed for hours/days…