back to the basics: truncate table reuse storage vs drop storage


30.12.2016
by Kamil Stawiarski

From time to time I get questions on my trainings, what is the difference between TRUNCATE TABLE and TRUNCATE TABLE DROP STORAGE… well, there is no difference because DROP STORAGE is default 😉

DROP STORAGE

Specify DROP STORAGE to deallocate all space from the deleted rows from the table except the space allocated by the MINEXTENTS parameter of the table. This space can subsequently be used by other objects in the tablespace. Oracle Database also sets the NEXT storage parameter to the size of the last extent removed from the segment in the truncation process. This setting, which is the default, is useful for small and medium-sized objects. The extent management in locally managed tablespace is very fast in these cases, so there is no need to reserve space.

Source: http://docs.oracle.com/database/122/SQLRF/TRUNCATE-TABLE.htm

But the most confusing part for most of the young DBAs and developers is the "DROP/REUSE STORAGE" clause itself – you have to understand, that truncate does not remove anything from the data files. Never. In both cases. The difference is how other objects behave in that tablespace. REUSE STORAGE means: "this is my private space and only I can reuse it".

You can use my ODBV tool to visualise it by yourself.

Here is an example:

Let’s create a simple tablespace and a table in it:

SQL> get tbs
  1  create tablespace truncate_test
  2  datafile '/u01/app/oracle/oradata/orcl/truncate_test.dbf' size 8m
  3  autoextend on next 8m
  4* maxsize 1g
SQL> /

Tablespace created.

SQL> conn hr/hr
Connected.
SQL> create table employees_truncate1 tablespace truncate_test
  2  as
  3  select *
  4  from employees;

Table created.

SQL> begin
  2    for i in 1..5 loop
  3      insert into employees_truncate1
  4      select *
  5      from employees_truncate1;
  6      commit;
  7    end loop;
  8  end;
  9  /

PL/SQL procedure successfully completed.

SQL> conn / as sysdba
Connected.
SQL> alter system checkpoint;

System altered.

Now we have to check the DATA_OBJECT_ID of this table in order to create ODBV parameter file, which will be used for visualisation:

SQL> ;
  1  select object_id, data_object_id, object_name
  2  from dba_objects
  3* where object_name like 'EMPLOYEES_TRUNC%'
SQL> /

 OBJECT_ID DATA_OBJECT_ID OBJECT_NAME
---------- -------------- ------------------------------
     94700	    94700 EMPLOYEES_TRUNCATE1

As you can see, at the beginning the OBJECT_ID and DATA_OBJECT_ID are the same. And as far as I know – OBJECT_ID can be never changed.

This is the visualisation of the table in the data file:

odbv_truncate1

You can see that table has 37 regular blocks and 6 empty blocks.

Now let’s truncate our table and check OBJECT_ID and DATA_OBJECT_ID:

SQL> truncate table employees_truncate1 ;

Table truncated.

SQL> get obj
  1  select object_id, data_object_id, object_name
  2  from dba_objects
  3* where object_name like 'EMPLOYEES_TRUNC%'
SQL> /

 OBJECT_ID DATA_OBJECT_ID OBJECT_NAME
---------- -------------- ------------------------------
     94700	    94701 EMPLOYEES_TRUNCATE1

You can see, that DATA_OBJECT_ID has changed. Now I will create a new table in the same tablespace and fill it with some rows:

SQL> create table employees_truncate2 tablespace truncate_test
  2  as
  3  select *
  4  from employees;

Table created.

SQL> insert into employees_truncate2 select * from employees_truncate2;

107 rows created.

SQL> /

214 rows created.

SQL> /

428 rows created.

SQL> commit;

Commit complete.

SQL> conn / as sysdba
Connected.
SQL> alter system checkpoint;

System altered.

SQL> get obj
  1  select object_id, data_object_id, object_name
  2  from dba_objects
  3* where object_name like 'EMPLOYEES_TRUNC%'
SQL>
SQL> /

 OBJECT_ID DATA_OBJECT_ID OBJECT_NAME
---------- -------------- ------------------------------
     94700	    94701 EMPLOYEES_TRUNCATE1
     94702	    94702 EMPLOYEES_TRUNCATE2

Based on the new values of DATA_OBJECT_ID, I will mark the "second instance" of the first table as Y and our new table as A.

This is the contents of the configuration file for ODBV:

[oracle@rico ~]$ cat trunc_obj
94700:X|BLUE
94701:Y|MAGENTA
94702:A|RED

And this is our visualisation:

odbv_truncate2

As you can see, the second table started consuming the blocks, which belonged to the table before truncate. So part of the data from the first iteration is still there, but the blocks are marked as reusable for other objects in the same tablespace.

If I’ll insert some data to the first table, the new iteration with new DATA_OBJECT_ID will be also consuming those blocks:

SQL> conn hr/hr
Connected.
SQL> insert into employees_truncate1
  2  select *
  3  from employees;

107 rows created.

SQL> /

107 rows created.

SQL> /

107 rows created.

SQL> commit;

Commit complete.

SQL> conn / as sysdba
Connected.
SQL> alter system checkpoint;

System altered.

odbv_truncate3

So after regular TRUNCATE TABLE (which is in fact: TRUNCATE TABLE DROP STORAGE), the data is not removed from the data files, but the blocks are simple marked to be reused by any segment in the same tablespace.

Now checkout the visualisation, when I repeat all above steps with only little alteration: I’ll use TRUNCATE TABLE RESUSE STORAGE instead of TRUNCATE TABLE:

odbv_truncate4

Now we can see, that the second table is not allowed to consume truncated blocks of the first table. Those blocks are marked for reuse, but only for the original owner.

So to sum up: in both cases, truncate does not remove anything from the datafile. It only marks blocks as reusable – for everyone or for the original owner.


Contact us

Database Whisperers sp. z o. o. sp. k.
al. Jerozolimskie 200, 3rd floor, room 342
02-486 Warszawa
NIP: 5272744987
REGON:362524978
+48 508 943 051
+48 661 966 009
info@ora-600.pl

Newsletter Sign up to be updated