пятница, 19 марта 2010 г.

Фрагментация таблиц в Oracle.

1. Для начала посмотрим размер таблицы(с фрагментацией)

SQL> SELECT TABLE_NAME, ROUND((BLOCKS*8),2)||'KB' "SIZE"
FROM USER_TABLES
WHERE TABLE_NAME = 'SESSION_TBL';

TABLE_NAME SIZE
------------------------------ ------------------------------------------
SESSION_TBL 7497760KB

2. Определим реальный размер данных

SQL> SELECT TABLE_NAME, ROUND((NUM_ROWS*AVG_ROW_LEN/1024),2)||'KB' "SIZE"
FROM USER_TABLES
WHERE TABLE_NAME = 'SESSION_TBL';

TABLE_NAME SIZE
------------------------------ ------------------------------------------
SESSION_TBL 4032361,52KB


В итоге 7497760KB - 4032361KB = 3465399 KB используется без толку.
В процентном соотношении 46% занятого пространства не используется.

3. Для удаления фрагментации потребуется реорганизовать таблицу.
Есть несколько опций для реорганизации фрагментированных таблиц.
Рассмотрим один вариант - перенос таблицы и пересоздание индексов.

4. Посмотрим какие индексы имеются в данной таблице

SQL> SELECT STATUS, INDEX_NAME FROM USER_INDEXES
WHERE TABLE_NAME = 'SESSION_TBL';

STATUS INDEX_NAME
-------- ------------------------------
VALID SYS_C005180
VALID ST_LCL_SES_STRT_TS

5. Начинаем. Необходимо, чтобы в tablespaces имелось свободное место.

SQL> ALTER TABLE SESSION_TBL MOVE;

Table altered.

6. Проверим индексы.

SQL> SELECT STATUS, INDEX_NAME FROM USER_INDEXES
WHERE TABLE_NAME = 'SESSION_TBL';

STATUS INDEX_NAME
-------- ------------------------------
UNUSABLE SYS_C005180
UNUSABLE ST_LCL_SES_STRT_TS

7. Пересоздаём индексы.

SQL> ALTER INDEX SYS_C005180 REBUILD;

Index altered.

SQL> ALTER INDEX ST_LCL_SES_STRT_TS REBUILD;

Index altered.

8. Проверяем.

SQL> SELECT STATUS, INDEX_NAME FROM USER_INDEXES
WHERE TABLE_NAME = 'SESSION_TBL';

STATUS INDEX_NAME
-------- ------------------------------
VALID SYS_C005180
VALID ST_LCL_SES_STRT_TS

8. Собираем статистику.

SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS('workusers','SESSION_TBL');

PL/SQL procedure successfully completed.

9. Проверяем размеры данных в даблице и размер самой таблицы.

SQL> SELECT TABLE_NAME, ROUND((BLOCKS*8),2)||'KB' "SIZE"
FROM USER_TABLES
WHERE TABLE_NAME = 'SESSION_TBL';

TABLE_NAME SIZE
------------------------------ ------------------------------------------
SESSION_TBL 4780632KB

SQL> SELECT TABLE_NAME, ROUND((NUM_ROWS*AVG_ROW_LEN/1024),2)||'KB' "SIZE"
FROM USER_TABLES
WHERE TABLE_NAME = 'SESSION_TBL';

TABLE_NAME SIZE
------------------------------ ------------------------------------------
SESSION_TBL 4032361,52KB

В итоге 4780632KB - 4032361KB = 748271KB


Т.е. освободилось 36% от ранее занятого таблицей пространства.

Составлено на основе материалов http://all-oracle.ru

Комментариев нет:

Отправить комментарий