20.02.2018 14:44
Как известно, от удаления данных в таблице она совсем не всегда "сжимается", а потому бывает, что в базе много невысвобожденного свободного места. Соответствующий отчет по таблицам есть в оптимизаторе, но разберем по основному источнику таких проблем - 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 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; 
и, в зависимости от полученных результатов, можно уточнить занятое место каждым конкретным сегментом
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_NAME) STORE AS (TABLESPACE &NEW_TABLESPACE); 
Часовой пояс GMT +3, время: 15:00.

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