小议lob字段结构和存储

Lob字段包含三个部分:Lob列、lob数据段、lob索引段。

Lob列由lob定位符也就是指向lob字段实际存放位置的指针和lob值组成。

Lob数据段可以分为多个chunk,每个chunk用来存放lob数据。

Lob索引段存放lob索引,由多个entry组成,每个entry结构大致为lob index locatorchunk idchunk location,一个entry指向一个lob块。也就是记录在lob索引段里面的entry等于lob数据段内的chunk数目。

结构大体如下:

Lob LOB定位符 lob

Lob数据段 chunk1 chunk2 chunk3 chunk4…

Log 索引段 entry entry entry entry…

SQL> create table tab_lob01(id number,cnt clob)

2 tablespace users

3 lob(cnt) store as seg_cnt01(tablespace netbaisdata

4 chunk 32K

5 pctversion 5

6 );

Table created

其中会创建一个表段,lob数据段和lob索引段,其中制定的seg_cnt01lob数据段存储在netbaisdata段内,而系统预定义的lob索引段也会存储在netbaisdata表空间中。

其中的上述的chunk也就是分配给lob段的最小单元,由于lob字段的读取和写入都是以chunk为单位,一般chunkdb_block_size的整数倍,oracle10g 版本最大值可以为2G,默认情况使用最小值。

Enable/disable storage in row

Enable storage in row模式表示小于4Klob字段存储在表段内,大于4klob字段存储在lob数据段内。

Disable storage in row不管lob字段的长度都存储在lob数据段内,仅仅只是在表的行内存储lob定位符。

Pctversion

Lob数据段不适用回滚机制,即当更新lob数据时,lob数据段内分配新chunk去插入一条新的记录,不对前映像修改,那么如果lob字段更新较多,肯定会产生很多的新version,会浪费较多的空间,所以需要用pctversion来控制前映像空间在lob数据空间中所占用的比例。大于此比例将会重用这些前映像,默认值是10%,最小设置为0,最大100%

Cache/nocache/cache read

Cache表示将lob数据段放在缓存中,nocache不放在缓存中,cache read则是读的时候会把lob存储在缓存中,默认的是nocache

Loc的存储位置:

根据lob字段的存储中的enable| disbale storage in row分析,当采用enable storage in row时,如果lob字段小于4K,也就是in-line blob的会直接存储在表段内;而当大于4K时(out-of-line)且lob字段没有超过12个的chunklob定位符直接指向lob数据段内的数据,不用lob索引段。Disable storage in row或者是二进制数据大于4k,而且超过12chunk时,需要通过lob定位符—lob索引段—lob数据段,也就是每一个lob数据段内的每个chunk地址都存在lob索引中。

SQL> select avg(dbms_lob.getlength(in_flow_img)) from ql_inf;

AVG(DBMS_LOB.GETLENGTH(IN_FLOW

------------------------------

93100.3484848485

SQL> select segment_name,chunk,pctversion,cache,logging,in_row from user_lobs where column_name='IN_FLOW_IMG' and table_name='QL_INF';

SEGMENT_NAME CHUNK PCTVERSION CACHE LOGGING IN_ROW

------------------------------ ---------- ---------- ---------- ------- ------

SYS_LOB0000052854C00019$$ 8192 10 NO YES YES

Lob字段in_flow_imgSYS_LOB0000052854C00019$$的默认chunk8kb,而实际我们存储的字段大概有91kb的样子,由于一个chunk只存储一行数据,实际会占用12chunk,那么会产生过多的行连接,这里设置较大的chunk会更好,不够在缺省的db_block_size 8kb下只能设置32kchunk,超过这个数在oracle10.2R下就会出现invalid lob option valueora-22851错误。当然如果实际的lob字段容量较小,比如4kb,而实际你的chunk默认的是8kb,由于chunk只存储一行数据,同样会占用8kb的大小,其余的空间也不会节省出来。

SQL> create table lob01(cnt1 clob,cnt2 clob) lob(cnt2) store as(disable storage in row);

Table created

SQL> insert into lob01 values(lpad('x',10000,'x'),rpad('x',10000,'x'))

;

2 /

1 row inserted

SQL> commit;

Commit complete

SQL> select avg(dbms_lob.getlength(cnt1)),avg(dbms_lob.getlength(cnt2)) from lob01;

AVG(DBMS_LOB.GETLENGTH(CNT1)) AVG(DBMS_LOB.GETLENGTH(CNT2))

----------------------------- -----------------------------

4000 4000

可以看出都应该在同一个chunk内,默认chunk8kb。那么disableenable所走的IO将不同。

SQL> set autotrace traceonly statistics

SQL> select cnt1 from lob01;

统计信息

----------------------------------------------------------

0 recursive calls

0 db block gets

11 consistent gets

4 physical reads

0 redo size

1023 bytes sent via SQL*Net to client

678 bytes received via SQL*Net from client

5 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

1 rows processed

SQL> select cnt2 from lob01;

统计信息

----------------------------------------------------------

0 recursive calls

0 db block gets

19 consistent gets

4 physical reads

0 redo size

963 bytes sent via SQL*Net to client

638 bytes received via SQL*Net from client

5 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

1 rows processed

多执行几次减小物理IO,可以看出真正的physical reads并不能绝对的减小到0,那是因为lob默认的是不会cache的。

SQL> alter table lob01 move tablespace netbaisdata

2 lob(cnt1) store as(cache)

3 lob(cnt2) store as(cache);

表已更改。

SQL> select cnt1 from lob01;

统计信息

----------------------------------------------------------

62 recursive calls

0 db block gets

23 consistent gets

3 physical reads

72 redo size

1023 bytes sent via SQL*Net to client

678 bytes received via SQL*Net from client

5 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

1 rows processed

SQL> select cnt1 from lob01;

统计信息

----------------------------------------------------------

0 recursive calls

0 db block gets

7 consistent gets

0 physical reads

0 redo size

1023 bytes sent via SQL*Net to client

678 bytes received via SQL*Net from client

5 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

1 rows processed

SQL> select cnt2 from lob01;

统计信息

----------------------------------------------------------

1 recursive calls

0 db block gets

15 consistent gets

0 physical reads

0 redo size

963 bytes sent via SQL*Net to client

638 bytes received via SQL*Net from client

5 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

1 rows processed

可以看出设置cache后,物理读会慢慢减少到0,全部转化为逻辑读,但是由于cnt2disable storage in row的,需要先根据lob定位器然后到lob索引段最后到lob数据段,需要访问更多的IO,所有逻辑读会大于cnt1.

接着看下面的事例:

SQL> select count(rowid) from jhqlnwhxdb.ql_inf;

COUNT(ROWID)

------------

16810

SQL> select count(rowid) from jhqlnwhxdb.ql_inf where dbms_lob.getlength(in_flow_img)>4096;

COUNT(ROWID)

------------

16803

SQL> select avg(dbms_lob.getlength(in_flow_img)) from jhqlnwhxdb.ql_inf where dbms_lob.getlength(in_flow_img)>4096;

AVG(DBMS_LOB.GETLENGTH(IN_FLOW

------------------------------

268087.183717193

可以看出in_flow_img的基本都大于4k,其大于4k的数据平均长度要达到160k的样子,如果大部分lob字段小于4k,则肯定是enable storage in row模式优先,有效的减少了行链接,而如果大于4k但是还是没有超过12chunk,其实也就是数据的长度没有达到缺省的12*8kb也就是96kb的值,也可以选择enable模式。如果大部分大于4k且基本超过了12 chunk值,也就是out-of-line存储的比例较高,应该选择disable模式,这样lob数据会存储在外面的lob数据段,如果进行fts或者查询非lob字段,将大大加快存储访问的速度,这个是需要dba更多的关注的,而另外也可以设置较大的chunkoracle每次的IO数据就会多一些,总体会减少相应的IO

Lob数据段和lob索引段可以分开存储到不同的tbs下,然后到不同的磁盘,减小磁盘的竞争,对于lob数据而言,只要一行数据超过oracle数据块的大小必产生行连接,我们可以通过analyze后来分析表中的行连接,通过oracle concept中就清楚设计中要相应的减少了行链接和行迁移,因为一旦过多的IO越来越多就可能往往成为你系统瓶颈的最终原因,不过生产中暂时还没有碰见这个成为瓶颈的案例。

SQL> analyze table jhqlnwhxdb.ql_inf compute statistics;

Table analyzed

SQL> select chain_cnt from dba_tables where table_Name='QL_INF' and

2 owner='JHQLNWHXDB';

CHAIN_CNT

----------

220

[@more@]

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/25362835/viewspace-1058577/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/25362835/viewspace-1058577/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值