BLOB读取怎样优化? BLOB读取怎样优化?我想把0.0 - 0.5M的许多文件,存到BLOB中,一个文件对应表中一行希望能快速的读取请问除了正常建表,还有什么可优化的地方,如块的大小、单个表的大小有什么需注意的吗?请高手多指点 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 -- 弄懂下面这些,你就清楚啦:-- 12.7.1 内部LOB ( P545 )create table t( id int primary key, txt clob)/eygle@SZTYORA> select dbms_metadata.get_ddl('TABLE','T') from dual;DBMS_METADATA.GET_DDL('TABLE','T')-------------------------------------------------------------------------------- CREATE TABLE "EYGLE"."T" ( "ID" NUMBER(*,0), "TXT" CLOB, PRIMARY KEY ("ID") USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT) TABLESPACE "EYGLE" ENABLE ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT) TABLESPACE "EYGLE" LOB ("TXT") STORE AS ( TABLESPACE "EYGLE" ENABLE STORAGE IN ROW CHUNK 8192 PCTVERSION 10 NOCACHE LOGGING STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT))-- LOB显然有以下属性:-- *(1) 一个表空间(这个例子中即为USERS)-- *(2) ENABLE STORAGE IN ROW作为一个默认属性-- *(3) CHUNK 8192-- *(4) PCTVERSION 10-- *(5) NOCACHE-- *(6) 一个完整的STORAGE子句-- 由此说明,在底层LOB并不那么简单,而事实上确实如此。LOB列总是会带来一种多段对象(multisegment object,这是我对它的叫法),-- 也就是说,这个表会使用多个物理段。如果我们在一个空模式中创建这个表,就会发现以下结果:select segment_name, segment_typefrom user_segments;SEGMENT_NAME SEGMENT_TYPE----------------------------------- ------------------------------SYS_LOB0000056912C00002$$ LOBSEGMENTT TABLESYS_C006746 INDEXSYS_IL0000056912C00002$$ LOBINDEX......-------------------------------------------------------------------------------------------------------- 注意 LOB可能是内联的(inline),或者存储在表中。在这种情况下,LOB数据会被缓存,但是这只适用于小于4000字节的LOB。-- 我们将在“IN ROW子句”一节中进一步讨论这种情况。------------------------------------------------------------------------------------------------------......-- *2) IN ROW子句 ( P548 )-- 前面的DBMS_METADATA返回的CREATE TABLE语句还包括以下内容:LOB ("TXT") STORE AS (... ENABLE STORAGE IN RAW ...-- 这控制了LOB数据是否总与表分开存储(存储在lobsegment中),或是有时可以与表一同存储,而不用单独放在lobsegment中。如果设置了ENABLE STORAGE IN ROW,-- 而不是DISABLE STORAGE IN ROW,小LOB(最多4000字节)就会像VARCHAR2一样存储在表本身中。只有当LOB超过了4000字节时,才会“移出”到lobsegment中。create table t( id int primary key, in_row clob, out_row clob)lob (in_row) store as (enable storage in row)lob (out_row) store as (disable storage in row);-- 在这个表中,我们将插入一些串数据,所有这些串的长度都不超过4000字节:insert into tselect rownum, owner || ' ' || object_name || ' ' || object_type || ' ' || status, owner || ' ' || object_name || ' ' || object_type || ' ' || statusfrom all_objects;commit;-- 现在,如果我们想读取每一行,在此使用了DBMS_MONITOR包,并启用了SQL_TRACE,执行这个工作时,可以看到这两个表获取数据时的性能:grant execute on dbms_monitor to eygle;declare l_cnt number; l_data varchar2(32765);begin select count(*) into l_cnt from t; dbms_monitor.session_trace_enable; for i in 1 .. l_cnt loop select in_row into l_data from t where id = i; select out_row into l_data from t where id = i; end loop;end;/......-- 这种行内/行外存储设置不仅会影响读,还会影响修改。如果我们要用小串更新前100行,并用小串插入100个新行,再使用上述同样的技术查看性能,会观察到:create sequence s start with 100000;declare l_cnt number; l_data varchar2(32765);begin dbms_monitor.session_trace_enable; for i in 1 .. 100 loop update t set in_row = to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') where id = i; update t set out_row = to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') where id = i; insert into t(id,in_row) values ( s.nextval, 'Hello World' ); insert into t(id,out_row) values ( s.nextval, 'Hello World' ); end loop;end;/......-- 注意读和写使用的I/O都有所增加。总之,由此显示出,如果使用一个CLOB,而且很多串都能在“行内”放下(也就是说,小于4000字节),-- 那么使用默认的ENABLE STORAGE IN ROW设置就是一个不错的想法。-- *3) CHUNK 子句 ( P553 )-- 前面的DBMS_METADATA返回的CREATE TABLE语句包括以下内容:LOB ("TXT") STORE AS ( ... CHUNK 8192 ... )-- LOB存储在块(chunk)中;指向LOB数据的索引会指向各个数据块。块(chunk)是逻辑上连续的一组数据块(block),这也是LOB的最小分配 单元,-- 而通常数据库的最小分配单元是数据库块。CHUNK大小必须是Oracle块大小的整数倍,只有这样才是合法值。-- 从两个角度看,选择CHUNK大小时必须当心。首先,每个LOB实例(每个行外存储的LOB值)会占用至少一个CHUNK。一个CHUNK由一个LOB值使用。如果一个表有100行,-- 而每行有一个包含7KB数据的LOB,你就会分配100个CHUNK,如果将CHUNK大小设置为32KB,就会分配100个32KB的CHUNK。如果将CHUNK大小设置为8KB,则(可能)分配100个8KB的CHUNK。-- 关键是,一个CHUNK只能由一个LOB使用(两个LOB不会使用同一个CHUNK)。如果选择了一个CHUNK大小,但不符合你期望的LOB大小,最后就会浪费大量的空间。例如,-- 如果表中的LOB平均有7KB,而你使用的CHUNK大小为32KB,对于每个LOB实例你都会“浪费”大约25KB的空间。另一方面,倘若使用8KB的CHUNK,就能使浪费减至最少。-- *4.) PCTVERSION 子句-- 前面的DBMS_METADATA返回的CREATE TABLE语句包括以下内容:LOB ("TXT") STORE AS ( ... PCTVERSION 10 ... )-- 这是用于控制LOB的读一致性。在前面的几章节中,我们已经讨论了读一致性、多版本和undo在其中所起的作用。但LOB实现读一致性的方式有所不同。-- lobsegment并不使用undo来记录其修改;而是直接在lobsegment本身中维护信息的版本。lobindex会像其他字段一样生成undo,但是lobsegment不会。相反,修改一个LOB时,-- Oracle会分配一个新的CHUNK,并且仍保留原来的CHUNK。如果回滚了事务,对LOB索引所做的修改会回滚,索引将再次指向原来的CHUNK。因此,undo维护会在LOB段本身中执行。-- 修改数据时,原来的数据保持不动,此外会创建新数据。create table t( id int primary key, txt clob)lob ( txt ) store as ( disable storage in row )/insert into t values (1, 'hello world' );commit;declare l_clob clob; cursor c is select id from t; l_id number;begin select txt into l_clob from t; open c; update t set id = 2, txt = 'Goodbye'; commit; dbms_output.put_line( dbms_lob.substr( l_clob, 100, 1 ) ); fetch c into l_id; dbms_output.put_line( 'id = ' || l_id ); close c;end;/select * from t;......-- PCTVERSION控制着用于实现LOB数据版本化的已分配LOB空间的百分比(这些数据库块由某个时间点的LOB所用,并处在lobsegment的HWM以下)。对于许多使用情况来说,-- 默认设置10%就足够了,因为在很多情况下,你只是要INSERT和获取LOB(通常不会执行LOB的更新;LOB往往会插入一次,而获取多次)。因此,-- 不必为LOB版本化预留太多的空间(甚至可以没有)。-- 不过,如果你的应用确实经常修改LOB,倘若你频繁地读LOB,与此同时另外某个会话正在修改这些LOB,10%可能就太小了。如果处理LOB时遇到一个ORA-22924错误,-- 解决方案并不是增加undo保留时间(UNDO_RETENTION),如果你在使用手动undo管理,那么增加更多RBS空间也不能解决这个问题。而是应该使用以下命令:ALTER TABLE tabname MODIFY LOB (lobname) ( PCTVERSION n );-- 并增加lobsegment中为实现数据版本化所用的空间大小。-- *5) RETENTION子句 ( P556 )-- 这个子句与PCTVERSION子句是互斥的,如果数据库中使用自动undo管理,就可以使用这个子句。RETENTION子句并非在lobsegment中保留某个百分比的空间来实现LOB的版本化,-- 而是使用基于时间的机制来保留数据。数据库会设置参数UNDO_RETENTION,指定要把undo信息保留多长时间来保证一致读。在这种情况下,这个参数也适用于LOB数据。-- 需要注意,不能使用这个子句来指定保留时间;而是从数据库的UNDO_RETENTION设置来继承它。-- *6) CACHE子句 ( P556 )-- 前面的DBMS_METADATA返回的CREATE TABLE语句包括以下内容:LOB ("TXT") STORE AS ( ... NOCACHE ... )-- 除了NOCACHE,这个选项还可以是CACHE或CACHE READS。这个子句控制了lobsegment数据是否存储在缓冲区缓存中。默认的NOCACHE指示,-- 每个访问都是从磁盘的一个直接读,类似地,每个写/修改都是对磁盘的一个直接写。CACHE READS允许缓存从磁盘读的LOB数据,但是LOB数据的写操作必须直接写至磁盘。-- CACHE则允许读和写时都能缓存LOB数据。-- 在许多情况下,默认设置可能对我们并不合适。如果你只有小规模或中等规模的LOB(例如,使用LOB来存储只有几KB的描述性字段),对其缓存就很有意义。如果不缓存,-- 当用户更新描述字段时,还必须等待I/O将数据写至磁盘(将执行一个CHUNK大小的I/O,而且用户要等待这个I/O完成)。如果你在执行多个LOB的加载,-- 那么加载每一行时都必须等待这个I/O完成。所以启用这些LOB的缓存很合理。你可以打开和关闭缓存,来看看会有什么影响:ALTER TABLE tbname MODIFY LOB (lobname) ( CACHE );ALTER TABLE tbname MODIFY LOB (lobname) ( CACHE READS);ALTER TABLE tbname MODIFY LOB (lobname) ( NOCACHE );-- 对于一个规模很大的初始加载,启用LOB的缓存就很有意义,这允许DBWR在后台将LOB数据写至磁盘,而你的客户应用可以继续加载更多的数据。-- 对于频繁访问或修改的小到中等规模的LOB,缓存就很合理,可以避免让最终用户实时等待物理I/O完成。不过,对于一个大小为50MB的LOB,把它放在缓存中就没有道理了。-- 要记住,此时可以充分使用Keep池或回收池。并非在默认缓存中将lobsegment数据与所有“常规”数据一同缓存,可以使用保持池或回收池将其分开缓存。-- 采用这种方式,既能缓存LOB数据,而且不影响系统中现有数据的缓存。-- *7) LOB STORAGE 子句-- 最后,前面的DBMS_METADATA返回的CREATE TABLE语句还包括以下内容:LOB ("TXT") STORE AS ( ... STORAGE(INITIAL 65536 NEXT 1048576MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1FREELIST GROUPS 1 BUFFER_POOL DEFAULT ) ... )-- 也就是说,它有一个完整的存储子句,可以用来控制物理存储特征。需要指出,这个存储子句同样适用于lobsegment 和lobindex,对一个段的设置也可以用于另一个段。-- 假设有一个本地管理的表空间,LOB的相关设置将是FREELISTS、FREELIST GROUPS和BUFFER_POOL,我们在第10章讨论过FREELISTS和FREELIST GROUPS与表段的关系。-- 这些讨论同样适用于lobindex段,因为lobindex与其他索引段的管理是一样的。如果需要高度并发地修改LOB,可能最好在索引段上设置多个FREELISTS。-- 上一节已经提到,对LOB段使用保持池或回收池可能是一个很有用的技术,这样就能缓存LOB数据,而且不会“破坏”现有的默认缓冲区缓存。-- 并不是将LOB与常规表一同放在块缓冲区中,可以在SGA中专门为这些LOB对象预留一段专用的内存。BUFFER_POOL子句可以达到这个目的。 BLOB类型 默认就是类似于外部表结构,本身就能提供很快的读取。 SQL code-- 弄懂下面这些,你就清楚啦:-- 12.7.1 内部LOB ( P545 )create table t( id int primary key,txt clob)/eygle@SZTYORA> select dbms_metadata.get_ddl('TABLE','T') from dual;DBMS_METADATA.GET_DDL('T…… 感谢帮助,感谢luoyoumou解答如果有具体的优化方法就更好了,谢谢 请问查询一个表中有3条以上A B C字段重复的数据,中的D这个怎么写? 如何优化包含CLOB字段的多字段索引 请高手解决,急 存储过程 多条件组合查询 Oracle安装问题 帮忙看下这个存储过程吧。急。。 在pl/sql环境下怎么将excel表中数据导入SQL数据库已有表中?? SQL语句 多用户信息对象映射问题! 与递归查询的问题 ---高手请进(在线等待) oracle 服务个数 Oracle在使用sys/change_on_install登录到sqlplus,浏览器em中登录不进去()
-- 12.7.1 内部LOB ( P545 )create table t
( id int primary key,
txt clob
)
/eygle@SZTYORA> select dbms_metadata.get_ddl('TABLE','T') from dual;DBMS_METADATA.GET_DDL('TABLE','T')
-------------------------------------------------------------------------------- CREATE TABLE "EYGLE"."T"
( "ID" NUMBER(*,0),
"TXT" CLOB,
PRIMARY KEY ("ID")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "EYGLE" ENABLE
) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "EYGLE"
LOB ("TXT") STORE AS (
TABLESPACE "EYGLE" ENABLE STORAGE IN ROW CHUNK 8192 PCTVERSION 10
NOCACHE LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT))-- LOB显然有以下属性:
-- *(1) 一个表空间(这个例子中即为USERS)
-- *(2) ENABLE STORAGE IN ROW作为一个默认属性
-- *(3) CHUNK 8192
-- *(4) PCTVERSION 10
-- *(5) NOCACHE
-- *(6) 一个完整的STORAGE子句-- 由此说明,在底层LOB并不那么简单,而事实上确实如此。LOB列总是会带来一种多段对象(multisegment object,这是我对它的叫法),
-- 也就是说,这个表会使用多个物理段。如果我们在一个空模式中创建这个表,就会发现以下结果:
select segment_name, segment_type
from user_segments;SEGMENT_NAME SEGMENT_TYPE
----------------------------------- ------------------------------
SYS_LOB0000056912C00002$$ LOBSEGMENT
T TABLE
SYS_C006746 INDEX
SYS_IL0000056912C00002$$ LOBINDEX......------------------------------------------------------------------------------------------------------
-- 注意 LOB可能是内联的(inline),或者存储在表中。在这种情况下,LOB数据会被缓存,但是这只适用于小于4000字节的LOB。
-- 我们将在“IN ROW子句”一节中进一步讨论这种情况。
------------------------------------------------------------------------------------------------------......-- *2) IN ROW子句 ( P548 )
-- 前面的DBMS_METADATA返回的CREATE TABLE语句还包括以下内容:
LOB ("TXT") STORE AS (... ENABLE STORAGE IN RAW ...-- 这控制了LOB数据是否总与表分开存储(存储在lobsegment中),或是有时可以与表一同存储,而不用单独放在lobsegment中。如果设置了ENABLE STORAGE IN ROW,
-- 而不是DISABLE STORAGE IN ROW,小LOB(最多4000字节)就会像VARCHAR2一样存储在表本身中。只有当LOB超过了4000字节时,才会“移出”到lobsegment中。create table t
( id int primary key,
in_row clob,
out_row clob
)
lob (in_row) store as (enable storage in row)
lob (out_row) store as (disable storage in row);-- 在这个表中,我们将插入一些串数据,所有这些串的长度都不超过4000字节:
insert into t
select rownum,
owner || ' ' || object_name || ' ' || object_type || ' ' || status,
owner || ' ' || object_name || ' ' || object_type || ' ' || status
from all_objects;commit;-- 现在,如果我们想读取每一行,在此使用了DBMS_MONITOR包,并启用了SQL_TRACE,执行这个工作时,可以看到这两个表获取数据时的性能:
grant execute on dbms_monitor to eygle;declare
l_cnt number;
l_data varchar2(32765);
begin
select count(*) into l_cnt from t; dbms_monitor.session_trace_enable;
for i in 1 .. l_cnt
loop
select in_row into l_data from t where id = i;
select out_row into l_data from t where id = i;
end loop;
end;
/......-- 这种行内/行外存储设置不仅会影响读,还会影响修改。如果我们要用小串更新前100行,并用小串插入100个新行,再使用上述同样的技术查看性能,会观察到:
create sequence s start with 100000;declare
l_cnt number;
l_data varchar2(32765);
begin
dbms_monitor.session_trace_enable;
for i in 1 .. 100
loop
update t set in_row = to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') where id = i;
update t set out_row = to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') where id = i;
insert into t(id,in_row) values ( s.nextval, 'Hello World' );
insert into t(id,out_row) values ( s.nextval, 'Hello World' );
end loop;
end;
/......-- 注意读和写使用的I/O都有所增加。总之,由此显示出,如果使用一个CLOB,而且很多串都能在“行内”放下(也就是说,小于4000字节),
-- 那么使用默认的ENABLE STORAGE IN ROW设置就是一个不错的想法。-- *3) CHUNK 子句 ( P553 )
-- 前面的DBMS_METADATA返回的CREATE TABLE语句包括以下内容:
LOB ("TXT") STORE AS ( ... CHUNK 8192 ... )-- LOB存储在块(chunk)中;指向LOB数据的索引会指向各个数据块。块(chunk)是逻辑上连续的一组数据块(block),这也是LOB的最小分配 单元,
-- 而通常数据库的最小分配单元是数据库块。CHUNK大小必须是Oracle块大小的整数倍,只有这样才是合法值。-- 从两个角度看,选择CHUNK大小时必须当心。首先,每个LOB实例(每个行外存储的LOB值)会占用至少一个CHUNK。一个CHUNK由一个LOB值使用。如果一个表有100行,
-- 而每行有一个包含7KB数据的LOB,你就会分配100个CHUNK,如果将CHUNK大小设置为32KB,就会分配100个32KB的CHUNK。如果将CHUNK大小设置为8KB,则(可能)分配100个8KB的CHUNK。
-- 关键是,一个CHUNK只能由一个LOB使用(两个LOB不会使用同一个CHUNK)。如果选择了一个CHUNK大小,但不符合你期望的LOB大小,最后就会浪费大量的空间。例如,
-- 如果表中的LOB平均有7KB,而你使用的CHUNK大小为32KB,对于每个LOB实例你都会“浪费”大约25KB的空间。另一方面,倘若使用8KB的CHUNK,就能使浪费减至最少。-- *4.) PCTVERSION 子句
-- 前面的DBMS_METADATA返回的CREATE TABLE语句包括以下内容:
LOB ("TXT") STORE AS ( ... PCTVERSION 10 ... )-- 这是用于控制LOB的读一致性。在前面的几章节中,我们已经讨论了读一致性、多版本和undo在其中所起的作用。但LOB实现读一致性的方式有所不同。
-- lobsegment并不使用undo来记录其修改;而是直接在lobsegment本身中维护信息的版本。lobindex会像其他字段一样生成undo,但是lobsegment不会。相反,修改一个LOB时,
-- Oracle会分配一个新的CHUNK,并且仍保留原来的CHUNK。如果回滚了事务,对LOB索引所做的修改会回滚,索引将再次指向原来的CHUNK。因此,undo维护会在LOB段本身中执行。
-- 修改数据时,原来的数据保持不动,此外会创建新数据。
create table t
( id int primary key,
txt clob
)
lob ( txt ) store as ( disable storage in row )
/insert into t values (1, 'hello world' );commit;declare
l_clob clob; cursor c is select id from t;
l_id number;
begin
select txt into l_clob from t;
open c;
update t set id = 2, txt = 'Goodbye';
commit;
dbms_output.put_line( dbms_lob.substr( l_clob, 100, 1 ) );
fetch c into l_id;
dbms_output.put_line( 'id = ' || l_id );
close c;
end;
/select * from t;......-- PCTVERSION控制着用于实现LOB数据版本化的已分配LOB空间的百分比(这些数据库块由某个时间点的LOB所用,并处在lobsegment的HWM以下)。对于许多使用情况来说,
-- 默认设置10%就足够了,因为在很多情况下,你只是要INSERT和获取LOB(通常不会执行LOB的更新;LOB往往会插入一次,而获取多次)。因此,
-- 不必为LOB版本化预留太多的空间(甚至可以没有)。-- 不过,如果你的应用确实经常修改LOB,倘若你频繁地读LOB,与此同时另外某个会话正在修改这些LOB,10%可能就太小了。如果处理LOB时遇到一个ORA-22924错误,
-- 解决方案并不是增加undo保留时间(UNDO_RETENTION),如果你在使用手动undo管理,那么增加更多RBS空间也不能解决这个问题。而是应该使用以下命令:
ALTER TABLE tabname MODIFY LOB (lobname) ( PCTVERSION n );-- 并增加lobsegment中为实现数据版本化所用的空间大小。-- *5) RETENTION子句 ( P556 )
-- 这个子句与PCTVERSION子句是互斥的,如果数据库中使用自动undo管理,就可以使用这个子句。RETENTION子句并非在lobsegment中保留某个百分比的空间来实现LOB的版本化,
-- 而是使用基于时间的机制来保留数据。数据库会设置参数UNDO_RETENTION,指定要把undo信息保留多长时间来保证一致读。在这种情况下,这个参数也适用于LOB数据。-- 需要注意,不能使用这个子句来指定保留时间;而是从数据库的UNDO_RETENTION设置来继承它。-- *6) CACHE子句 ( P556 )
-- 前面的DBMS_METADATA返回的CREATE TABLE语句包括以下内容:
LOB ("TXT") STORE AS ( ... NOCACHE ... )-- 除了NOCACHE,这个选项还可以是CACHE或CACHE READS。这个子句控制了lobsegment数据是否存储在缓冲区缓存中。默认的NOCACHE指示,
-- 每个访问都是从磁盘的一个直接读,类似地,每个写/修改都是对磁盘的一个直接写。CACHE READS允许缓存从磁盘读的LOB数据,但是LOB数据的写操作必须直接写至磁盘。
-- CACHE则允许读和写时都能缓存LOB数据。-- 在许多情况下,默认设置可能对我们并不合适。如果你只有小规模或中等规模的LOB(例如,使用LOB来存储只有几KB的描述性字段),对其缓存就很有意义。如果不缓存,
-- 当用户更新描述字段时,还必须等待I/O将数据写至磁盘(将执行一个CHUNK大小的I/O,而且用户要等待这个I/O完成)。如果你在执行多个LOB的加载,
-- 那么加载每一行时都必须等待这个I/O完成。所以启用这些LOB的缓存很合理。你可以打开和关闭缓存,来看看会有什么影响:
ALTER TABLE tbname MODIFY LOB (lobname) ( CACHE );
ALTER TABLE tbname MODIFY LOB (lobname) ( CACHE READS);
ALTER TABLE tbname MODIFY LOB (lobname) ( NOCACHE );-- 对于一个规模很大的初始加载,启用LOB的缓存就很有意义,这允许DBWR在后台将LOB数据写至磁盘,而你的客户应用可以继续加载更多的数据。
-- 对于频繁访问或修改的小到中等规模的LOB,缓存就很合理,可以避免让最终用户实时等待物理I/O完成。不过,对于一个大小为50MB的LOB,把它放在缓存中就没有道理了。-- 要记住,此时可以充分使用Keep池或回收池。并非在默认缓存中将lobsegment数据与所有“常规”数据一同缓存,可以使用保持池或回收池将其分开缓存。
-- 采用这种方式,既能缓存LOB数据,而且不影响系统中现有数据的缓存。-- *7) LOB STORAGE 子句
-- 最后,前面的DBMS_METADATA返回的CREATE TABLE语句还包括以下内容:
LOB ("TXT") STORE AS ( ... STORAGE(INITIAL 65536 NEXT 1048576
MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1
FREELIST GROUPS 1 BUFFER_POOL DEFAULT ) ... )-- 也就是说,它有一个完整的存储子句,可以用来控制物理存储特征。需要指出,这个存储子句同样适用于lobsegment 和lobindex,对一个段的设置也可以用于另一个段。
-- 假设有一个本地管理的表空间,LOB的相关设置将是FREELISTS、FREELIST GROUPS和BUFFER_POOL,我们在第10章讨论过FREELISTS和FREELIST GROUPS与表段的关系。
-- 这些讨论同样适用于lobindex段,因为lobindex与其他索引段的管理是一样的。如果需要高度并发地修改LOB,可能最好在索引段上设置多个FREELISTS。-- 上一节已经提到,对LOB段使用保持池或回收池可能是一个很有用的技术,这样就能缓存LOB数据,而且不会“破坏”现有的默认缓冲区缓存。
-- 并不是将LOB与常规表一同放在块缓冲区中,可以在SGA中专门为这些LOB对象预留一段专用的内存。BUFFER_POOL子句可以达到这个目的。
-- 弄懂下面这些,你就清楚啦:
-- 12.7.1 内部LOB ( P545 )create table t
( id int primary key,
txt clob
)
/eygle@SZTYORA> select dbms_metadata.get_ddl('TABLE','T') from dual;DBMS_METADATA.GET_DDL('T……
如果有具体的优化方法就更好了,谢谢