【问题标题】:Oracle - is there any performance hit for a CLOB column that contains rows with less than 4K rows vs a Varchar column?Oracle - 对于包含少于 4K 行的行的 CLOB 列与 Varchar 列相比,性能是否受到影响?
【发布时间】:2016-08-04 20:08:27
【问题描述】:

如果您需要存储大部分(如果不是全部)小于 4K 字节的字符串,那么在 VARCHAR2 数据类型上使用 CLOB 数据类型是否有任何负面影响?

来自here

CLOB 可以存储在单独的 LOB 段中,指向 LOB 段的指针与表的其余数据一起存储在数据块中。如果使用 CREATE TABLE 语句,您可以使用 LOB 存储子句控制 LOB 段的存储位置。默认情况下,小于约 4000 字节的 LOB 将以与 VARCHAR2 相同的方式存储,即与其余数据保持一致。

来自here

当您创建具有 CLOB 列的表时,有一个用于 CLOB 的名为“启用行内存储”的选项。这决定了 CLOB 是存储在与表相同的段中,因此是与表行的其余部分一起存储,还是单独存储在单独的段中。在第二种情况下,表行将包含指向 CLOB 数据位置的指针。一般情况下,将CLOB与表行一起存储效率更高,但是如果CLOB超过4000个字符左右,则不能再存储在行中,而不管是否启用存储在行中,都存储在CLOB段中与否。

从这些陈述中,我觉得将列声明为 CLOB 并没有任何惩罚,即使所有行都包含少于 4K 的行。这准确吗?

【问题讨论】:

    标签: oracle varchar clob varchar2


    【解决方案1】:

    当您使用 LOB 数据类型时会产生重大影响,例如:

    • 取决于您读取数据的方式,即使数据存储在行中,每行 LOB 访问也可能意味着额外的网络往返
    • 优化器可以在 VARCHAR 列、直方图、更精确的长度、绑定窥视等上使用更多统计信息。
    • 某些执行计划优化不适用于 LOB 列,例如分解子查询的具体化
    • 许多 SQL 函数不能与 LOB 一起使用。

    额外往返示例:

    HUSQVIK@hq_pdb_tcp> CREATE TABLE t_varchar AS SELECT CAST('data' AS VARCHAR2(4)) c1 FROM DUAL CONNECT BY LEVEL <= 10;
    
    Table created.
    
    HUSQVIK@hq_pdb_tcp> CREATE TABLE t_clob AS SELECT to_clob('data') c1 FROM DUAL CONNECT BY LEVEL <= 10;
    
    Table created.
    
    HUSQVIK@hq_pdb_tcp> SET AUTOT TRACE
    HUSQVIK@hq_pdb_tcp> SELECT * FROM t_varchar;
    
    10 rows selected.
    
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 4100862799
    
    -------------------------------------------------------------------------------
    | Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
    -------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT  |           |    10 |    50 |     3   (0)| 00:00:01 |
    |   1 |  TABLE ACCESS FULL| T_VARCHAR |    10 |    50 |     3   (0)| 00:00:01 |
    -------------------------------------------------------------------------------
    
    
    Statistics
    ----------------------------------------------------------
              5  recursive calls
              0  db block gets
              5  consistent gets
              5  physical reads
              0  redo size
            682  bytes sent via SQL*Net to client
            551  bytes received via SQL*Net from client
              2  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
             10  rows processed
    
    HUSQVIK@hq_pdb_tcp> SELECT * FROM t_clob;
    
    10 rows selected.
    
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 3459655851
    
    ----------------------------------------------------------------------------
    | Id  | Operation         | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
    ----------------------------------------------------------------------------
    |   0 | SELECT STATEMENT  |        |    10 |   410 |     3   (0)| 00:00:01 |
    |   1 |  TABLE ACCESS FULL| T_CLOB |    10 |   410 |     3   (0)| 00:00:01 |
    ----------------------------------------------------------------------------
    
    
    Statistics
    ----------------------------------------------------------
              2  recursive calls
              0  db block gets
             23  consistent gets
              5  physical reads
              0  redo size
           3433  bytes sent via SQL*Net to client
           3231  bytes received via SQL*Net from client
             12  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
             10  rows processed
    

    还要注意增加的一致获取数量,因为 Oracle 在每次往返中一遍又一遍地处理包含 LOB 数据的同一块。

    【讨论】:

    • 数据按行存储,怎么还有额外的往返?
    • @MatthewMoisen 据我所知,行为取决于您使用的驱动程序或其设置,我在 SQL*Plus 中添加了一个简单示例,其中我无法在同一往返中获取 LOB 数据.
    猜你喜欢
    • 2016-07-26
    • 2013-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-11
    • 1970-01-01
    • 2015-08-10
    相关资源
    最近更新 更多