一,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 |
|
This is not possible with either a |
Only the LOB locator is stored in the table column; 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 |
When you access a LOB column, you can choose to fetch the locator or the data. |
When you access a |
A LOB can be up to 128 terabytes or more in size depending on your block size. |
A |
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 |
You can replicate LOBs in both local and distributed environments. |
Replication in both local and distributed environments is not possible with a |
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树索引或者位图索引。
如有错误,望不吝指出