20.02.2018 14:44
OlegON
 
Как известно, от удаления данных в таблице она совсем не всегда "сжимается", а потому бывает, что в базе много невысвобожденного свободного места. Соответствующий отчет по таблицам есть в оптимизаторе, но разберем по основному источнику таких проблем - LOB-сегментам. Итак, для начала выведем список сегментов по убыванию размера
SQL код:
SELECT l.table_name,
L.COLUMN_NAME,
s.segment_name,
S.TABLESPACE_NAME,
l.owner,
round(s.bytes 1024 1024 1024) AS "GB"
FROM dba_lobs ldba_segments s
WHERE s
.segment_name l.segment_name
AND s.owner l.owner
AND s.segment_type 'LOBSEGMENT'
ORDER BY bytes DESC
и, в зависимости от полученных результатов, можно уточнить занятое место каждым конкретным сегментом
SQL код:
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;

оцениваем результаты. Если много UNUSED, то, если не планируется их в ближайшее время занять, можно отобрать их командой, которая откидывает пустое место в хвосте таблицы
SQL код:
ALTER TABLE &TABLE_NAME MODIFY LOB (&COLUMN_NAME) (DEALLOCATE UNUSED); 
однако, иногда данные рассредоточены по всей таблице россыпью и, например, в 2Тб LOB в самом хвосте несколько килобайт, которые не дают половину свободного места высвободить. На этот случай можно выполнить команду
SQL код:
ALTER TABLE &TABLE_NAME MODIFY LOB (&COLUMN_NAME) (SHRINK SPACE COMPACT CASCADE); 
Обратите внимание, что эта операция блокирующая и занимает много времени, поэтому в рабочее время ее запускать нельзя.
Как вариант можно перенести весь LOB в отдельное табличное пространство.
SQL код:
ALTER TABLE &TABLE_NAME MOVE LOB (&SEGMENT_NAMESTORE AS (TABLESPACE &NEW_TABLESPACE); 
Часовой пояс GMT +3, время: 01:25.

Форум на базе vBulletin®
Copyright © Jelsoft Enterprises Ltd.
В случае заимствования информации гипертекстовая индексируемая ссылка на Форум обязательна.