Интернет-журнал «FORS» Архив номеров На Главную

Опыт использования таблиц с LOB-столбцами

 

Тихомиров Владимир Вадимович,
Директор по информационным технологиям ОСАО “Ингосстрах”

Михеичев Валерий Вадимович,
Эксперт Oracle, ОСАО “Ингосстрах”

Существует несколько типов LOB объектов: BLOB (двоичный большой объект), CLOB (символьный большой объект), NCLOB (национальный символьный большой объект) и BFILE (внешний двоичный файл). LOB объекты делятся на внутренние и внешние.

Внутренние большие объекты Internal LOB – хранятся в базах данных (БД), к ним относятся BLOB, CLOB и NCLOB. Внутренние большие объекты могут быть постоянными или временными:

Внешние большие объекты External LOB – вид данных, который хранится в файлах операционной системы, вне базы данных, а в базе данных на них хранятся ссылки (локаторы). Внешние LOB используют тип данных – BFILE.

LOB объект состоит из двух частей:

Инструментом работы с LOB выступает пакет DBMS_LOB. Он предоставляет методы манипулирования внутренними и внешними LOBами.

В данной статье рассматриваются только постоянные внутренние LOB объекты.

Сегменты LOB объектов Oracle

При создании и заполнении данными таких объектов Oracle как LOB объект, таблица, индекс и др. для каждого объекта создается структура, называемая сегментом. При этом имеется особенность при создании сегментов: для каждой не секционированной таблицы создается только один сегмент, для одного не секционированного индекса создается только один сегмент, для каждой секции секционированной таблицы и для каждой секции индекса создается свой сегмент. Однако для каждого LOB столбца таблицы создается не один, а два сегмента. Один сегмент - это LOB-сегмент для хранения данных и второй – это LOB индексный сегмент. LOB индексный сегмент создается автоматически при создании LOB-сегмента и служит для навигации по LOB-сегменту.

Таким образом, если в таблице было указано N столбцов типа LOB, то получим 2*N LOB-сегментов.

LOB сегменты можно увидеть из представления DBA_LOBS запросом:

Select  owner, table_name, column_name, segment_name, index_name, tablespace_name
From DBA_LOBS  Where Owner=’ИМЯ СХЕМЫ’ and Table_name = ‘ИМЯ ТАБЛИЦЫ’;

Рассмотрим порядок работы с таблицами, имеющими LOB столбцы, на примере таблицы AIS.SERVICEMSGXML, функционирующей в нашей системе. В таблице имеются два LOB столбца: XMLOUT и XMLIN - оба типа CLOB.

Команда создания таблицы имеет вид:

CREATE TABLE AIS.SERVICEMSGXML
(  ISN           NUMBER,
  XMLOUT        CLOB,
  BMLIN            CLOB
  )
TABLESPACE ADATA
LOB (XMLOUT) STORE AS 
      ( TABLESPACE  LOBTBS 
        ENABLE      STORAGE IN ROW
       CHUNK     16384)
LOB (XMLIN) STORE AS 
      ( TABLESPACE  LOBTBS2 
        ENABLE      STORAGE IN ROW
        CHUNK       8192    );

LOB сегменты этой таблицы можно увидеть из представления DBA_LOBS указанным выше запросом:

Select  * From DBA_LOBS  Where owner=’AIS’ and table_name = ‘SERVICEMSGXML’;

В результате получаем:

OWNER	TABLE_NAME	COLUMN_NAME	SEGMENT_NAME			INDEX_NAME			TABLESPACE_NAME
AIS	SERVICEMSGXML	XMLOUT		SYS_LOB0001677384C00014$$	SYS_IL0001677384C00014$$	LOBTBS
AIS	SERVICEMSGXML	XMLIN		SYS_LOB0001677384C00015$$	SYS_IL0001677384C00015$$	LOBTBS2

Мы видим, что в именах сегментов имеются символы SYS_LOB для LOB-сегментов и SYS_IL для индексных сегментов.

Используя представление Oracle DBA_SEGMENTS (при наличии данных в LOB), можно получить размер в байтах, занимаемых LOB-сегментами и LOB-индексными сегментами. Например, для LOB столбца XMLOUT число байтов, занимаемых сегментом, определяется запросом, указанным ниже. При этом в запросе в поле segment_name подставляется имя сегмента, полученного из представления DBA_LOBS.

Select owner, segment_name, bytes, tablespace_name From DBA_SEGMENTS Where segment_name = ‘SYS_LOB0001677384C00014$$';

В результате работы запроса получаем:

OWNER	SEGMENT_NAME			BYTES		TABLESPACE_NAME
AIS	SYS_LOB0001677384C00014$$	6969884672	LOBTBS

Для работы с LOB удобным является запрос, в котором используются оба указанных выше представления: DBA_SEGMENTS и DBA_LOBS. Данный запрос покажет (при наличии данных в LOB) не только LOB сегменты всей таблицы и ее индексов, но и размеры в байтах, которые они занимают.

 
Select s.owner, d.table_name, d.column_name, s.segment_name, s.segment_type, s. bytes,
s.tablespace_name From DBA_SEGMENTS s, DBA_LOBS d
Where s.segment_name in (d.segment_name,d.index_name) and s.owner=d.owner
and d.owner='AIS' and d.table_name = 'SERVICEMSGXML' order by 3;

OWNER	TABLE_NAME	COLUMN_NAME	SEGMENT_NAME			SEGMENT_TYPE	BYTES
AIS	SERVICEMSGXML	XMLIN		SYS_IL0001677384C00015$$	LOBINDEX	65536
AIS	SERVICEMSGXML	XMLIN		SYS_LOB0001677384C00015$$	LOBSEGMENT	131072
AIS	SERVICEMSGXML	XMLOUT		SYS_LOB0001677384C00014$$	LOBSEGMENT	6969884672
AIS	SERVICEMSGXML	XMLOUT		SYS_IL0001677384C00014$$	LOBINDEX	6291456

Иногда важно посмотреть объем, занимаемый самой таблицей без LOB объектов. Это можно увидеть (при наличии данных в таблице) запросом:

Select s.owner, s.segment_name, s.segment_type, s.bytes, s.tablespace_name
From DBA_SEGMENTS s Where owner='AIS' and  segment_name = 'SERVICEMSGXML';

OWNER	SEGMENT_NAME	SEGMENT_TYPE	TABLESPACE_NAME	BYTES
AIS	SERVICEMSGXML	TABLE	ADATA	8388608

Как видно, сама таблица составляет порядка 8 MB, в то время как один из LOB занимает 6900 MB. В силу чего таблица была размещена в табличном пространство ADATA среднего размера, в то время как LOB большого объема был размещен в другом существенно большем табличном пространстве LOBTBS. О табличных пространствах LOB изложено ниже.

Задание табличного пространства для LOB столбцов таблицы

По умолчанию LOB-сегмент со своим LOB индексным сегментом создается в том же табличном пространстве, что и таблица, в которой находятся LOB столбец. При этом весьма важный момент: LOB-сегмент и LOB-индекс всегда находятся в одном и том же табличном пространстве.

Однако порой целесообразно помещать LOB сегмент в табличное пространство, отличное от пространства таблицы. При этом сами LOB столбцы так же могут размещаться в различных табличных пространствах.

Для размещения LOB в другое табличное пространство, отличное от пространства таблицы, используется структура STORE (начиная с Oracle 11g можно использовать структуру STORE AS SECUREFILE) в команде CREATE таблицы. При этом фразу STORE можно указать только при создании таблицы, т.е. STORE нельзя вставить в процессе модификации таблицы.

Замечание. При создании таблицы по команде Create table с LOB столбцами в ней автоматически для каждого LOB столбца таблицы создается структура STORE. Например, для столбца XMLOUT типа LOB по умолчанию создалась бы структура STORE вида:

LOB (XMLOUT) STORE AS (
TABLESPACE  ADATA
ENABLE      STORAGE IN ROW
CHUNK       8192
RETENTION
NOCACHE
LOGGING).

В ней по умолчанию табличным пространство LOB-а становиться табличное пространство таблицы ADATA и автоматически создаются несколько параметров.

Если есть необходимость управлять табличным пространством или параметрами STORE, надо явно описать конструкцию STORE при создании таблицы (что и было сделано при создании таблицы AIS.SERVICEMSGXML по каждому LOB столбцу). При этом, если используется конструкция STORE AS SECUREFILE, то ее необходимо явно прописывать в команде Create table.

Основными атрибутами конструкции STORE являются:

В Oracle 11g структура STORE получила дальнейшее развитие, так появилась возможность сжимать данные LOB-ов и исключить их дублирование. Для этого вместо конструкции STORE пишется конструкция STORE AS SECUREFILE. В ней дополнительно к существующим атрибутам добавились новые атрибуты, среди них:

Вывод. При создании STORE cледует оценить, что эффективнее: хранить LOB в таблице или вынести их из таблицы (режим ENABLE или DISABLE), обосновать целесообразность кэширования LOB и определить более эффективный размер CHUNK.

Модификация атрибутов конструкции STORE

Ряд атрибутов STORE могут быть добавлены или модифицированы в любой момент после создания таблицы командой ALTER TABLE (не модифицируются такие атрибуты как CHUNK и ENABLE/DISABLE STORAGE IN ROW).

Например, для столбца XMLIN таблицы SERVICEMSGXML модификация атрибутов NOCACHE на CACHE осуществляется так же по команде ALTER

ALTER TABLE  AIS.SERVICEMSGXML MODIFY     LOB (XMLIN)  (CACHE);

Для режима STORE AS SECUREFILE можно модифицировать или добавлять новые атрибуты. Например, добавить DEDUPLICATE и модифицировать COMPRESS с LOW на HIGH по команде:

ALTER TABLE  AIS.SERVICEMSGXML MODIFY   LOB (XMLIN)  (DEDUPLICATE);
ALTER TABLE  AIS.SERVICEMSGXML MODIFY   LOB(XMLIN) (COMPRESS HIGH);

Особенности очистки табличного пространства, занимаемого LOB объектами

В отличие от обычных таблиц удаление данных из таблицы с LOB не освобождает табличное пространство, занимаемое LOB. Для освобождения табличного пространства используется команда SHRINK либо TRUNCATE таблицы или (что более эффективно) TRUNCATE секции для секционированных таблиц.

Сжатие пространства для не секционированной таблицы осуществляется по команде

ALTER TABLE SERVICEMSGXML  MODIFY LOB (XMLIN) (SHRINK SPACE CASCADE);

Для секционированной таблицы команды с shrink и truncate имеют вид:

ALTER TABLE имя таблицы   MODIFY PARTITION имя партиции
LOB (имя LOB столбца) (SHRINK SPACE);
ALTER TABLE имя таблицы   TRUNCATE PARTITION имя партиции
UPDATE GLOBAL INDEXES;

Фраза UPDATE GLOBAL INDEXES в TRUNCATE обеспечивает исправность глобальных индексов после очистки секции по Truncate.

Выводы

  1. Для каждого LOB столбца таблицы автоматически создают два LOB сегмента.
  2. По умолчанию LOB сегменты попадают в то же табличное пространство, что и таблица. Если LOB столбцы требуется размещать в другое табличное пространство, то используется конструкция STORE или STORE AS SECUREFILE.
    Дальнейшим развитием конструкции STORE в Oracle 11g является новая конструкция STORE AS SECUREFILE , позволяющая сжимать и уменьшать число дублирующей информации в LOB объектах.
  3. Возможна модификация ряда атрибутов конструкции STORE (STORE AS SECUREFILE).
  4. Для сжатия табличного пространства LOB объектов используюсь shrink или truncate.
  5.