Вы находитесь на странице: 1из 7

Table fragmentation & how to avoid 

same
January 20, 2011 by samadhan

When a lot of DML operations are applied on a table, the table will become fragmented
because DML does not release free space from the table below the HWM.

HWM is an indicator of USED BLOCKS in the database. Blocks below the high water
mark (used blocks) have at least once contained data. This data might have been deleted.
Since Oracle knows that blocks beyond the high water mark don’t have data, it only reads
blocks up to the high water mark when doing a full table scan.

DDL statement always resets the HWM.

Small example to find the table fragmentation.

SQL> select count(*) from big1;

1000000 rows selected.

SQL> delete from big1 where rownum <= 300000;

300000 rows deleted.

SQL> commit;

Commit complete.

SQL> update big1 set object_id = 0 where rownum <=350000;

342226 rows updated.

SQL> commit;

Commit complete.

SQL> exec dbms_stats.gather_table_stats(‘SCOTT’,'BIG1′);

PL/SQL procedure successfully completed.

SQL> select table_name, round((blocks*8),2) tablesize, round((num_rows*avg_row_l


en/1024),2) actualsize from dba_tables  where table_name=’BIG1′;

TABLE_NAME TABLE SIZE ACTUAL DATA


————————— ——————————————- ——————
BIG1              72952          30604.2
Note = 72952 – 30604 = 42348 Kb is wasted space in table
 

The difference between two values is 60% and Pctfree 10% (default) – so, the table has
50% extra space which is wasted because there is no data.

How to reset HWM / remove fragemenation?

For that we need to reorganize the fragmented table.

We have four options to reorganize fragmented tables:

1. alter table … move + rebuild indexes


2. export / truncate / import
3. create table as select ( CTAS)
4. dbms_redefinition

Option: 1 “alter table … move + rebuild indexes”

SQL> alter table BIG1 move;

Table altered.

SQL> select status,index_name from user_indexes


2 where table_name = ‘BIG1′;

STATUS INDEX_NAME
——– ——————————
UNUSABLE BIGIDX

SQL> alter index bigidx rebuild;

Index altered.

SQL> select status,index_name from user_indexes


2 where table_name = ‘BIG1′;

STATUS INDEX_NAME
——– ——————————
VALID BIGIDX

SQL> exec dbms_stats.gather_table_stats(‘SCOTT’,'BIG1′);

PL/SQL procedure successfully completed.


SQL> select table_name, round((blocks*8),2) tablesize, round((num_rows*avg_row_l
en/1024),2) actualsize from dba_tables  where table_name=’BIG1′;

TABLE_NAME TABLE SIZE ACTUAL DATA


————————— ——————————————- ——————
BIG1              38224           30727.37

Option: 2 “Create table as select”

SQL> create table big2 as select * from big1;

Table created.

SQL> drop table big1 purge;

Table dropped.

SQL> rename big2 to big1;

Table renamed.

SQL> exec dbms_stats.gather_table_stats(‘SCOTT’,'BIG1′);

PL/SQL procedure successfully completed.

SQL> select table_name, round((blocks*8),2) tablesize, round((num_rows*avg_row_l


en/1024),2) actualsize from dba_tables  where table_name=’BIG1′;

TABLE_NAME TABLE SIZE ACTUAL DATA


————————— ——————————————- ——————
BIG1              85536            68986.97

SQL> select status from user_indexes


2 where table_name = ‘BIG1′;

no rows selected

SQL> –Note we need to create all indexes.

Option: 3 “export / truncate / import”

SQL> select table_name, round((blocks*8),2)||’kb’ “size”


2 from user_tables
3 where table_name = ‘BIG1′;
TABLE_NAME size
—————————— ——————————————
BIG1 85536kb

SQL> select table_name, round((num_rows*avg_row_len/1024),2)||’kb’ “size”


2 from user_tables
3 where table_name = ‘BIG1′;

TABLE_NAME size
—————————— ——————————————
BIG1 42535.54kb

SQL> select status from user_indexes where table_name = ‘BIG1′;

STATUS
——–
VALID

SQL> exit
Disconnected from Oracle Database 10g Enterprise Edition Release 10.1.0.5.0 – Pr
oduction
With the Partitioning, OLAP and Data Mining options

C:\>exp scott/tiger@Orcl file=c:\big1.dmp tables=big1

Export: Release 10.1.0.5.0 – Production on…..

Export terminated successfully without warnings.

SQL> truncate table big1;

Table truncated.

imp scott/tiger@Orcl file=c:\big1.dmp ignore=y

Import: Release 10.1.0.5.0 – Production on….

Import terminated successfully without warnings.

SQL> select table_name, round((blocks*8),2)||’kb’ “size”


2 from user_tables
3 where table_name = ‘BIG1′;

TABLE_NAME size
—————————— ——————————————
BIG1 85536kb
SQL> select table_name, round((num_rows*avg_row_len/1024),2)||’kb’ “size”
2 from user_tables
3 where table_name = ‘BIG1′;

TABLE_NAME size
—————————— ——————————————
BIG1 42535.54kb

SQL> exec dbms_stats.gather_table_stats(‘SCOTT’,'BIG1′);

PL/SQL procedure successfully completed.

SQL> select table_name, round((blocks*8),2)||’kb’ “size”


2 from user_tables
3 where table_name = ‘BIG1′;

TABLE_NAME size
—————————— ——————————————
BIG1 51840kb

SQL> select table_name, round((num_rows*avg_row_len/1024),2)||’kb’ “size”


2 from user_tables
3 where table_name = ‘BIG1′;

TABLE_NAME size
—————————— ——————————————
BIG1 42542.27kb

SQL> select status from user_indexes where table_name = ‘BIG1′;

STATUS
——–
VALID

SQL> exec dbms_redefinition.can_redef_table(‘SCOTT’,'BIG1′,-


> dbms_redefinition.cons_use_pk);

PL/SQL procedure successfully completed.

Option: 4 “dbms_redefinition”….Which we will disscus afterwords….

Expert are always welcome for their valuable comment or suggestion for the above
post.

 Share this:
 Email
 Facebook

Posted in Performance Tunning | Tagged Commit (data management), Database,


Fragmentation, Oracle Database, sql, table fragmentation | 3 Comments

Like
Be the first to like this post.

3 Responses

1. on February 10, 2011 at 7:58 am | Reply Vineet Arya

Hi,
If one is working on oracle 10g and above. Then i don’t think there will be much
table space fragmentation. There is a new feature in 10g called automatic segment
space management which prevents fragmentation. However One may need to
reorganize the table because of some High number of chained (actually migrated)
rows.
Apart from the techniques that Samadhan already told. There is one more good
feature in oracle 10g called shrink space command. One can refer it on oracle
documentation.

o on February 10, 2011 at 8:35 am | Reply samadhan

Thnks Vineet….Keep replying….

o on February 17, 2011 at 3:35 pm | Reply samadhan

Hi Vineet,
As disscused please check the post for 10gR1 New Feature SEGMENT
SHRINKING.

http://samadhandba.wordpress.com/2011/02/17/how-to-adjust-the-high-
watermark-in-oracle-10g-%e2%80%93-alter-table-shrink/
Thx….

Вам также может понравиться