根据我阅读的文档,CLOB或BLOB的默认存储是内联的,这意味着如果大小小于大约4k,则它将存储在表中。
但是,当我在Oracle(10.2.0.1.0)中的虚拟表上对此进行测试时,Oracle Monitor(由Allround Automations提供)的性能和响应表明它与该表无关。
这是我的测试场景...
create table clobtest ( x int primary key, y clob, z varchar(100) )
;
insert into clobtest
select object_id, object_name, object_name
from all_objects where rownum < 10001
;
select COLUMN_NAME, IN_ROW
from user_lobs
where table_name = 'CLOBTEST'
;
这显示:Y YES(建议Oracle将Clob存储在行中)
select x, y from CLOBTEST where ROWNUM < 1001 -- 8.49 seconds
select x, z from CLOBTEST where ROWNUM < 1001 -- 0.298 seconds
因此,在这种情况下,CLOB值的最大长度为30个字符,因此应始终为内联。如果我运行Oracle Monitor,对于返回的每一行,它将显示一个LOB.Length以及一个LOB.Read(),再次表明该Clob值与表无关。
我也尝试过像这样创建表格
create table clobtest
( x int primary key, y clob, z varchar(100) )
LOB (y) STORE AS (ENABLE STORAGE IN ROW)
但是得到了完全一样的结果。
有人对我可以如何强制(说服,鼓励)Oracle在表中在线存储Clob值有任何建议吗? (我希望获得与读取varchar2列z相似的响应时间)
更新:如果我运行此SQL
select COLUMN_NAME, IN_ROW, l.SEGMENT_NAME, SEGMENT_TYPE, BYTES, BLOCKS, EXTENTS
from user_lobs l
JOIN USER_SEGMENTS s
on (l.Segment_Name = s. segment_name )
where table_name = 'CLOBTEST'
然后我得到以下结果...
Y YES SYS_LOB0000398621C00002$$ LOBSEGMENT 65536 8 1
最佳答案
Oracle LOB的行为如下。
在以下情况下,将内联存储LOB:
(
The size is lower or equal than 3964
AND
ENABLE STORAGE IN ROW has been defined in the LOB storage clause
) OR (
The value is NULL
)
在以下情况下,LOB将存储在行外:
(
The value is not NULL
) AND (
Its size is higher than 3964
OR
DISABLE STORAGE IN ROW has been defined in the LOB storage clause
)
现在,这不是可能影响性能的唯一问题。
如果最终未将LOB最终不内联存储,则Oracle的默认行为是避免对其进行缓存(只有内联LOB与该行的其他字段一起缓存在缓冲区高速缓存中)。为了告诉Oracle也缓存非内联LOB,在定义LOB时应使用CACHE选项。
默认行为是“行中启用存储”和“NOCACHE”,这意味着将内联小型LOB,大型LOB将不会(也不会被缓存)。
最后,在通信协议(protocol)级别还存在性能问题。典型的Oracle客户端将为每个LOB执行两次额外的往返操作以获取它们:
-检索LOB的大小并相应分配内存的工具
-一个用来获取数据本身的文件(前提是LOB很小)
即使使用数组接口(interface)检索结果,也会执行这些额外的往返。如果检索1000行并且数组大小足够大,则需要支付1次往返来检索行,并支付2000次往返来检索LOB的内容。
请注意,它是否而不是取决于LOB是否以内联方式存储。他们是完全不同的问题。
为了在协议(protocol)级别进行优化,Oracle提供了一个新的OCI动词,可以在一次往返中获取多个LOB(OCILobArrayRead)。我不知道JDBC是否存在类似的东西。
另一个选择是将LOB绑定(bind)在客户端,就好像它是一个大RAW/VARCHAR2。这仅在可以定义LOB的最大大小的情况下有效(因为必须在绑定(bind)时提供最大大小)。这个技巧避免了额外的漫游:LOB像RAW或VARCHAR2一样被处理。我们在LOB密集型应用程序中经常使用它。
一旦优化了往返次数,就可以在网络配置中调整数据包大小(SDU)的大小,以更好地适应这种情况(即,有限的大型往返次数)。它倾向于减少“SQL *从客户端获取更多数据”和“SQL *从客户端获取更多数据”的等待事件。
关于performance - Oracle 10g小Blob或Clob是否不能内联存储?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7361729/