【问题标题】:How big is an Oracle XMLType when stored as BINARY XML存储为 BINARY XML 时 Oracle XMLType 有多大
【发布时间】:2014-09-06 00:46:54
【问题描述】:

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 本身的存储大小呢?

请帮忙,表大小是 340GB,所以值得研究一下存储选项...

【问题讨论】:

标签: sql xml oracle oracle11gr2


【解决方案1】:

Oracle Binary XML 格式对应于“Compact Schema Aware XML Format”,缩写为 CSX。存储为 BLOB 字段的编码数据。有关二进制 XML 格式的详细信息,请参阅 Oracle 文档(herehere)。

数据字段的实际大小取决于 XMLType 列的 LOB 存储参数。例如。如果启用storage in row 选项,则小文档直接与其他数据一起存储,vsize() 返回适当的值。

实际上Oracle会创建带有系统名称的底层BLOB列,可以通过查询user_tab_cols视图找到:

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

【讨论】:

  • 太棒了,就是这样!对于 @gvenzl 的示例,它返回 getlength(x)=7371363,getlength(SYS_NC00002$)=4754521 用于 binaryxml_table,7170064 与 7170064 用于 clob_table。感谢您解决这个问题!
  • 我昨天晚上找到了你提到的那两篇论文,经过长时间的搜索!
  • 不客气 :) 感谢您纠正错误输入!
【解决方案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 

【讨论】:

  • 感谢您提供的精彩示例!您只存储一行,因此段大小应接近行大小。聪明的把戏!对于我的数据库,我得到 clob_table=7340032 和 binaryxml_table=6422528 的值。
  • 好吧,一个段与一行无关。段可以是表、表分区、索引、LOB,...重要的是在其中存储超过 4k,这样您的 lob 就不会“在线”存储,这意味着在实际的数据库块中行本身,但存储在“out line” LOB 段中。
【解决方案3】:

[rep issue,不允许发布 cmets] 正如我所理解的那样,您想说“问题之间”。唯一的相似之处是存储空间问题,认为它可能有助于“猜测”估计。您没有提到您将存储为 bXML 的数据类型。

将二进制 XML 解压成文本

如果是纯 XML,那么这取决于您要使用的压缩器。通常 lzma|gzip 用于二进制压缩。也许我写的东西太明显了,但我只知道这些

【讨论】:

  • 压缩器是Oracle实现的,他们说是“不透明”类型。
  • 让我澄清一下:在 Oracle 中,通常可以找出单个列的大小。例如vsize(number_col) 将在几个字节的范围内,dbms_lob.getlength(clob_col) 将为您提供 clob 的长度。我想了解如何对二进制 xmltype 列执行此操作。
猜你喜欢
  • 2012-02-15
  • 2015-03-01
  • 2013-09-02
  • 1970-01-01
  • 1970-01-01
  • 2013-12-28
  • 1970-01-01
  • 2022-01-10
  • 1970-01-01
相关资源
最近更新 更多