Oracle - 与 Varchar 列相比,包含少于 4K 行的行的 CLOB 列是否有任何性能影响?

Oracle - is there any performance hit for a CLOB column that contains rows with less than 4K rows vs a Varchar column?

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

来自here

A CLOB may be stored in a seperate LOB segment, with a pointer to the LOB segment stored in the data block with the rest of the table's data. You can control where the LOB segment is stored with the LOB storage clause if the CREATE TABLE statement. By default, a LOB less than about 4000 bytes will be stored the same way as a VARCHAR2, that is, in-line with the rest of the data.

来自here

When you create a table with a CLOB column, there is an option called 'Enable Storage In Row' for the CLOB. This dictates whether the CLOB is stored in the same segment as the table, and hence alongside the rest of the table row, or in a separate segment by itself. In the second case, the table row would then contain a pointer to the location of the CLOB data. Generally it is more efficient to store the CLOB with the table row, but if the CLOB is longer than about 4000 characters, it can no longer be stored in the row, and is stored in the CLOB segment regardless of whether storage in row in enabled or not.

从这些陈述来看,在我看来,即使所有行都包含少于 4K 行,将列声明为 CLOB 也没有任何惩罚。这准确吗?

使用 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 数据的同一块。