SHRINK или MOVE LOB сегмента
By: Date: 01.04.2015 Categories: !RUS,Admin,ORACLE Метки:

Как освободить место в табличном пространстве за счет LOB сегмента.

В статье описано как освободить место в табличном пространстве за счет LOB сегмент

Можно переместить LOB сегмент в табличное пространство, которое располагаются на более медленных устройствах хранения, но больших по объему и относительно дешевых.

Чтобы освободить место в табличном пространстве за счет LOB сегмента, можно использовать три способа:
A) Освободить неиспользуемое место выше High Water Mark (HWM).
B) Сделать SHRINK. В сегменте освободиться неиспользуемое место и место под удаленными данными.
C) Физически переместить LOB сегмент в другое табличное пространство.

ВНИМАНИЕ: Во время выполнения запросов из способов B) и C) LOB сегмент блокируется. Если LOB сегмент большой, то это может занять значительное время. Поэтому эти операции рекомендуется проводить во вне рабочее время.

Сначала определяем, с какими сегментами мы будем работать
0) Определяем размер LOB сегментов, чтобы понять какие из них самые большие

SELECT l.table_name,
L.COLUMN_NAME,
s.segment_name,
S.TABLESPACE_NAME,
l.owner,
s.bytes / 1024 / 1024 AS "MB"
FROM dba_lobs l, dba_segments s
WHERE     s.segment_name = l.segment_name
AND s.owner = l.owner
AND s.segment_type = 'LOBSEGMENT'
ORDER BY bytes DESC;

1) Сегмент может занимать больше места, чем в нем содержится данных. Этим запросом можно определить, сколько места занимают реальные данные конкретного сегмента.
Если место занимаемое данными намного меньше самого сегмента, значит есть свободное место в самом сегменте и его можно попробовать освободить способами A) и B)
Если данные занимают весь сегмент — значит чтобы освободить место в табличном пространстве его нужно переносить в другое табличное пространство.
Вместо переменных подставить:
<TABLE_NAME> — поле table_name из запроса 0
<SEGMENT_NAME> — поле segment_name из запроса 0

SELECT SUM (DBMS_LOB.getlength ('&SEGMENT_NAME')) / 1024 / 1024 AS "MB"
FROM &TABLE_NAME;

A)

A.1) Процедура показывает, сколько места можно освободить командой ALTER TABLE … DEALLOCATE UNUSED.
Если такого места много и вы хотите освободить его — выполните A.2.
Если такого места мало тогда место используйте способы B) или С).

DECLARE
TOTAL_BLOCKS                NUMBER;
TOTAL_BYTES                 NUMBER;
UNUSED_BLOCKS               NUMBER;
UNUSED_BYTES                NUMBER;
LAST_USED_EXTENT_FILE_ID    NUMBER;
LAST_USED_EXTENT_BLOCK_ID   NUMBER;
LAST_USED_BLOCK             NUMBER;
BEGIN
DBMS_SPACE.unused_space ('&OWNER',
'&SEGMENT_NAME',
'LOB',
TOTAL_BLOCKS,
TOTAL_BYTES,
UNUSED_BLOCKS,
UNUSED_BYTES,
LAST_USED_EXTENT_FILE_ID,
LAST_USED_EXTENT_BLOCK_ID,
LAST_USED_BLOCK);

DBMS_OUTPUT.put_line ('SEGMENT_NAME = <LOB SEGMENT NAME>');
DBMS_OUTPUT.put_line ('-');
DBMS_OUTPUT.put_line ('TOTAL_BLOCKS = ' || TOTAL_BLOCKS);
DBMS_OUTPUT.put_line ('TOTAL_BYTES = ' || TOTAL_BYTES);
DBMS_OUTPUT.put_line ('TOTAL_MB = ' || TOTAL_BYTES / 1024 / 1024);
DBMS_OUTPUT.put_line ('UNUSED_BLOCKS = ' || UNUSED_BLOCKS);
DBMS_OUTPUT.put_line ('UNUSED BYTES = ' || UNUSED_BYTES);
DBMS_OUTPUT.put_line ('UNUSED MB = ' || UNUSED_BYTES / 1024 / 1024);
DBMS_OUTPUT.put_line (
'LAST_USED_EXTENT_FILE_ID = ' || LAST_USED_EXTENT_FILE_ID);
DBMS_OUTPUT.put_line (
'LAST_USED_EXTENT_BLOCK_ID = ' || LAST_USED_EXTENT_BLOCK_ID);
DBMS_OUTPUT.put_line ('LAST_USED_BLOCK = ' || LAST_USED_BLOCK);
END;
/

A.2) Если такого места много его можно освободить командой
<TABLE_NAME> — поле table_name из запроса 0
<COLUMN_NAME> — поле COLUMN_NAME из запроса 0
alter table ELA_DOCUMENT modify lob (ELADO_BYTES) (deallocate unused);

ALTER TABLE &TABLE_NAME MODIFY LOB (&COLUMN_NAME) (DEALLOCATE UNUSED);

B)

B.1) Процедура показывает, сколько места можно освободить командой ALTER TABLE … DEALLOCATE UNUSED.
Если такого места много и вы хотите освободить его — выполните A.2.
Если такого места мало тогда место используте способы B) или С).
<TABLE_NAME> — поле table_name из запроса 0
<COLUMN_NAME> — поле COLUMN_NAME из запроса 0
alter table ELA_DOCUMENT modify lob(ELADO_BYTES) (shrink space);
alter table ELA_DOCUMENT modify lob(ELADO_BYTES) (shrink space cascade);
Опция cascade — применяет SHRINK не только к LOB сегменту но и к связанным с ним LOB индексам

ALTER TABLE &TABLE_NAME MODIFY LOB(&COLUMN_NAME) (SHRINK SPACE CASCADE);

C)

C.1) Запрос которым LOB сегмент переноситься в другое табличное пространство
Вместо переменных подставить:
<TABLE_NAME> — поле table_name из запроса 0
<COLUMN_NAME> — поле COLUMN_NAME из запроса 0
<NEW_TABLESPACE> — имя табличного пространства в которое вы хотите перенести LOB сегмент
ALTER TABLE ELA_DOCUMENT MOVE LOB(ELADO_BYTES) STORE AS (TABLESPACE DATA2);

ALTER TABLE &TABLE_NAME MOVE LOB(&SEGMENT_NAME) STORE AS (TABLESPACE &NEW_TABLESPACE);