Насколько велик XML-тип Oracle при хранении в виде BINARY XML

Документация Oracle утверждает, что она сохраняет XMLType более компактным как BINARY XML, чем CLOB. Но как узнать, сколько места занимает бинарный XML?

CREATE TABLE t (x XMLTYPE) XMLTYPE x STORE AS BINARY XML;

SELECT vsize(x), dbms_lob.getlength(XMLTYPE.getclobval(x)) FROM t;

94 135254
94  63848
94  60188

Итак, vsize представляется размером некоторого указателя или локатора LOB, а getclobval распаковывает двоичный XML-текст в текст. Но как насчет размера хранилища самого бинарного XML?

Пожалуйста, помогите, размер стола составляет 340 ГБ, поэтому стоит рассмотреть варианты хранения...

Ответ 1

Формат двоичного формата Oracle соответствует "Compact XML Schema Aware XML Format", сокращенно CSX. Закодированные данные сохраняются как поле BLOB. Подробная информация о бинарном формате XML доступна в документации Oracle (здесь и здесь).

Реальный размер поля данных зависит от параметров хранения больших объектов в столбце XMLType. Например. если включена опция storage in row, тогда небольшие документы, хранящиеся непосредственно с другими данными, и vsize() возвращают соответствующие значения.

В действительности Oracle создает базовый столбец BLOB с именем системы, который можно найти, запросив user_tab_cols view:

select table_name, column_name, data_type 
from user_tab_cols 
where 
  table_name = 'T' and hidden_column = 'YES'
  and
  column_id = (
      select column_id 
      from user_tab_cols 
      where table_name = 'T' and column_name = 'X'
  ) 

Этот запрос возвращает имя скрытого столбца системы, которое выглядит как SYS_NC00002$.

После этого можно получить размер полей с регулярным вызовом dbms_lob.getlength() против скрытого столбца:

select dbms_lob.getlength(SYS_NC00002$) from t

Ответ 2

Фактическое потребление памяти сохраняется в представлении, называемом user_segments. Чтобы найти коррелирующий LOB в столбце, вам придется присоединиться к user_segments с user_lobs:

CREATE TABLE clob_table (x XMLTYPE) XMLTYPE x store as CLOB;

CREATE TABLE binaryxml_table (x XMLTYPE) XMLTYPE x STORE AS BINARY XML;

INSERT INTO clob_table (x) SELECT
  XMLELEMENT("DatabaseObjects",
    XMLAGG(
      XMLELEMENT("Object", XMLATTRIBUTES(owner, object_type as type, created, status), object_name)
    )
  ) as x
FROM all_objects;

INSERT INTO binaryxml_table (x) select
  XMLELEMENT("DatabaseObjects",
    XMLAGG(
      XMLELEMENT("Object", XMLATTRIBUTES(owner, object_type as type, created, status), object_name)
    )
  ) as x
FROM all_objects;

SELECT lobs.table_name,
  (SELECT column_name
     FROM user_tab_cols
       WHERE table_name = lobs.table_name AND data_type = 'XMLTYPE'  AND column_id =
         (SELECT column_id
            FROM user_tab_cols
              WHERE table_name = lobs.table_name AND column_name = lobs.column_name
          )
    ) column_name,
  seg.segment_name, seg.bytes
    FROM user_lobs lobs, user_segments seg
      WHERE lobs.segment_name = seg.segment_name;

TABLE_NAME      COLUMN_NAME SEGMENT_NAME                 BYTES
--------------- ----------- ------------------------- --------
BINARYXML_TABLE X           SYS_LOB0000094730C00002$$  7536640 
CLOB_TABLE      X           SYS_LOB0000094727C00002$$ 19922944 

Ответ 3

[rep issue, не разрешено оставлять комментарии] вы хотели сказать "между вопросами", как я понял. единственное сходство - проблема с памятью, подумал, что это может быть полезно для оценки "догадки". вы не указали, какой тип данных вы собираетесь хранить как bXML.

распаковывает двоичный XML-текст в текст

Если чистый XML, то это зависит от того, какой компрессор вы собираетесь использовать. Обычно lzma | gzip используется для двоичного сжатия. Возможно, я пишу о слишком очевидных вещах, но все, что я знаю