LOB

时间:2021-12-09 10:52:56

一,LOB介绍

1,概念

LOB 是指用来存储大对象的数据类型,一般说LOB只是泛指,具体有BLOB,CLOB,NCLOB,BFILE。

   根据你数据库的设置,一个LOB可以存储的最大大小从8TB到128TB不等。

   它适用于存储半结构化和非结构化的数据。

  在早先的版本里,oracle提供的是LONG类型,虽然目前也一样提供,但oracle建议使用LOB而不是LONG。LOB对比LONG类型的优势在后面说明,可以通过alter table将LONG column转换为LOB类型。

2,LOB的类型

 内部 LOBs

 所谓的内部指的是数据存储在数据库的表空间里面,支持的类型有BLOB,CLOB,NCLOB。

另外还内部LOB还分为永久的和临时的两种类型。

 一个永久的LOB是指存在一个表行里面的LOB实例。而临时的LOB是在你本地应用的范围内,实例化的时候创建的。临时的LOB实例会在你将其插入DB的一个表行后实体化。

 实体化的LOB是符合ACID原则的,可以被提交/回滚,以及从事务或介质失败中恢复。

 外部LOBs以及BFILE

 外部LOBS是存储在操作系统文件中的数据对象,而不是存储在表空间里面。BFILE是唯一的外部LOB数据类型,是只读的,不能在application里面往BFILE里面写数据。

 所以以下情况就比较适用BFILE:

  • 应用运行过程中不会变化的二进制数据,比如说图案

  • 数据会被导入到其他类型的LOB中进行操作,也就是BFILE里的数据会被读进BLOB或者说CLOB里面进行操作

  • 流数据,只需要读的多媒体数据

  • SIZE很大的只读数据,借此避免使用太多的数据库空间

 操作系统上的任何存储设备都可以用来保存BFILE数据,比如硬盘驱动,CD-ROMs, PhotoCDs以及DVDs.

BLOB 二进制
存储任意类型的二进制格式的数据,通常来说用于多媒体数据,比如图像,音频和视频
CLOB 字符型
存储字符串数据,专指数据库的字符集类型,此类字符是固定宽度格式的
NCLOB 国家字符集
存储的也是字符数据,只不过这里的字符是国家字符集内的字符。字符宽度不固定
BFILE 外部二进制文件
存储在操作系统文件系统的二进制文件,可以被DB表所访问。BFILE是只读的,一般用于存储静态数据(或者说你不需要直接变更的)
如果需要变更,可以将BFILE内的数据读进相对应的其他LOB类型中

3,Lob Locator

 一个LOB实例有一个定位器和一个数值。LOB定位器用于定位LOB数据的物理存储位置,你可以把它当成指针来看。  

 有时候当你在某个操作里面传递一个LOB,其实传递的只是Locator而已。

 这里稍微提一下LOB定位器(Blob, Clob, NCLOB)跟BFILE定位器的区别, 前者是每一行都会存储一个定位器,即便数据一样,在DML过程中也会生成一份Copy。

 后者的定位器则是指向操作系统的BFILE文件,不同BFILE的locator是独立的。如果不同的行指向同一个BFILE,则locator是一样的,在insert过程中,只有locator被插入表中。

Note: DB还可以自定义创建一些数据类型以LOB形式存储,比如VARRAY,XMLType

二,LOB存储

1,LOB值可以被初始化为NULL或者Empty,两者的不同的地方的是,NULL是没有locator的,存储的是NULL,这里要注意的是,这里是初始化的时候如果这么设置才会没有locator,后续的变化还是会生成locator的。

 Empty则是空值,会有一个locator, 只不过LOB的长度为0.

 可以通过以下sql判断是否有null值

SELECT COUNT (*) FROM print_media WHERE ad_graphic IS NULL;

 NULL值的LOB无法直接通过OCI或者DBMS_LOB来进行操作,必须先将其更新为非NULL值或者Empty。 因为这些功能/函数,是和locator进行交互的。

 通过以下方式设置为Empty:

INSERT INTO a_table VALUES (EMPTY_BLOB());

 总的来说,初始化的时候,用以下方式将还未存放数据的LOBs设置为NULL或者Empty:

INSERT INTO print_media VALUES (1001, EMPTY_CLOB(), EMPTY_CLOB(), NULL,
    EMPTY_BLOB(), EMPTY_BLOB(), NULL, NULL, NULL, NULL);

 BFILE可以通过BFILENAME()来设置NULL或者文件名字

2,LOBs和LONG的对比

LOB Data Type LONG and LONG RAW Data Type

You can store multiple LOBs in a single row

You can store only one LONG or LONG RAW in each row.

LOBs can be attributes of a user-defined datatype

This is not possible with either a LONG or LONG RAW

Only the LOB locator is stored in the table column; BLOB and CLOB data can be stored in separate tablespaces and BFILE data is stored as an external file.

For inline LOBs, the database will store LOBs that are less than approximately 4000 bytes of data in the table column.

In the case of a LONG or LONG RAW the entire value is stored in the table column.

When you access a LOB column, you can choose to fetch the locator or the data.

When you access a LONG or LONG RAW, the entire value is returned.

A LOB can be up to 128 terabytes or more in size depending on your block size.

LONG or LONG RAW instance is limited to 2 gigabytes in size.

There is greater flexibility in manipulating data in a random, piece-wise manner with LOBs. LOBs can be accessed at random offsets.

Less flexibility in manipulating data in a random, piece-wise manner with LONG or LONG RAW data.LONGs must be accessed from the beginning to the desired location.

You can replicate LOBs in both local and distributed environments.

Replication in both local and distributed environments is not possible with a LONG or LONG RAW (see Oracle Database Advanced Replication)

3,LOB Value的存储位置

根据创建表时指定的列参数,以及LOB的大小,实际的LOB Value的存储位置分为行内存储和行外存储。

LOB值存储在行外的情况有:

a) 创建表的时候设置了DISABLE STORAGE IN ROW

b) Lob的大小超过了4000 Bytes (4000减去系统控制信息),也就是说不是足量的4000

c) 原本大小超过4000的LOB更新后小于4000,依旧会存储在行外。

LOB值存储在行内的情况有:

a) 当LOB值的大小小于4000Byte的时候,或者显示设置了ENABLE STORAGE IN ROW(或者说没有指定这个参数,也就是默认)

b) 当LOB值为空的时候

Note: 使用默认的LOB存储参数可以获得更好的数据库性能。能够避免大量创建和管理小的LOB数据。如果你存储的LOB数值大多数时候是小的,那么建议使用行内存储。

  • Locator总是存储在行内

  • 任意一个LOB实例都会有一个locator,不管你的存储参数是什么,也不管你的LOB值是多少

  • 如果一个LOB创建的时候指定了外部存储,并且BASICFILE LOB存有任意数据,那么最少会使用一个CHUNK大小的存储空间,即便LOB的大小小于CHUNK的大小,这里就是存储的额外开销

  • 如果一个LOB的列初始化为Empty, 那么那一行只会存储一个locator,不会有额外的存储被使用

  • 如果LOB的存储参数没有影响BFILE列,那么BFILE的数据总是存储在数据库以外的操作系统文件里面

当你创建LOB对象的时候,你可以为每一个LOB列指定一个表空间,并且设置相应的存储参数,比如说CHUNK size.

4,CHUNK, 它是LOB存储的最小单元。一个CHUNK可以是一个或者多个oracle数据块,它的大小不是固定的,可以在创建表的时候指定。默认情况,CHUNK的大小等于一个表空间块的大小,最大值是32K。

 CHUNK的一部分是用来存储系统相关信息(额外开销),剩下的部分才用来存储LOB数据。可以通过DBMS_LOB.GETCHUNKSIZE来获取lob的chunk size. OCI里面,通过OCILobGetChunkSize()获取。

 当LOB列创建完成后,CHUNK的大小就不能再改变了,因此在创建之前确定好CHUNK的大小很重要。而对于SECUREFILE LOBs来说,指定的chunk size只是一个建议值,更多是为了向后兼容的目的。

 PS:SecureFile跟BASICFile可以看下 https://www.oracle.com/technetwork/database/securefiles-160920-zhs.html

 CHUNK的值对行内存储的LOB没有影响。只有当行外存储的时候,不恰当的CHUNK SIZE可能会导致大量空间的浪费。

Data Size CHUNK Size Disk Space Used to Store the LOB Space Utilization (Percent)

3500 enable storage in row

irrelevant

3500 in row

100

3500 disable storage in row

32 KB

32 KB

10

3500 disable storage in row

4 KB

4 KB

90

33 KB

32 KB

64 KB

51

2 GB +10

32 KB

2 GB + 32 KB

99+

  关于设置CHUNK的大小,要结合你经常访问的数据大小,假如你经常只访问一个块,那chunk size设置为这个块的大小是最合适的。但是假如你需要访问的LOB数据量都很大,比如2G,那么SIZE设置为32KB的时候,性能是最好的。

5,表空间和LOB索引

 对于LOBs来说,最好是指定一个独立的表空间,这样子可以获得最好的性能表现。如果很多不同的LOB访问非常频繁,甚至可以为每一个LOB column单独指定一个表空间,以此来分散设备的争用。

 LOB索引是跟LOB存储强相关的内部结构,这意味着用户不能单独删掉或者重建它们。

 Note:

 LOB index不能被altered

 当你建表的时候,如果你为一个非分区表的LOB索引指定了一个表空间,这个指定将会被忽略掉,LOB索引会和LOB数据存储在同一个表空间中。 分区表没有LOB index的语法。

 可以在LOB列上创建的索引有:域索引,文本索引,函数索引,扩展索引

Note:

  当你移走一个LOB列后,整个表的所有索引都要重建。

  不能在LOB列上创建B树索引或者位图索引。

如有错误,望不吝指出