测试LOB的SECUREFILE存储方式时发现,如果利用SQLLDR的TRUNCATE方式导入数据,随着测试次数的增加,LOB对象占用的空间也会逐步增加。
创建表的脚本很简单:
CREATE TABLE t_load_4m_sf (id NUMBER, full_name varchar2(100), create_date DATE, contents BLOB, CONSTRAINT pk_t_load_4m_sf PRIMARY KEY(id)) lob (contents) store AS securefile; |
用于加载LOB数据的控制文件如下:
[oracle@dbserver1 sqlldr]$ more sqlldr_4M_sf.ctl LOAD DATA INFILE 'filename.dat' INTO TABLE T_LOAD_4M_SF TRUNCATE FIELDS TERMINATED BY ',' (ID CHAR(255), FULL_NAME CHAR(255), CREATE_DATE SYSDATE, CONTENTS LOBFILE(FULL_NAME) TERMINATED BY EOF) |
数据文件格式如下:
[oracle@dbserver1 sqlldr]$ more filename.dat 1,/home/oracle/2M/IMG_5015.JPG 2,/home/oracle/2M/IMG_5016.JPG 3,/home/oracle/2M/IMG_5017.JPG 4,/home/oracle/2M/IMG_5018.JPG 5,/home/oracle/2M/IMG_5022.JPG 6,/home/oracle/2M/IMG_5023.JPG 7,/home/oracle/2M/IMG_5025.JPG . . . 663,/home/oracle/2M/DSC00142.JPG 664,/home/oracle/2M/DSC00143.JPG |
导入命令如下:
[oracle@dbserver1 sqlldr]$ sqlldr enmotest/oracle control=sqlldr_4M_sf.ctl SQL*Loader: Release 11.2.0.2.0 - Production ON Mon Aug 8 17:32:54 2011 Copyright (c) 1982, 2009, Oracle AND/OR its affiliates. ALL rights reserved. Commit point reached - logical record COUNT 64 Commit point reached - logical record COUNT 128 Commit point reached - logical record COUNT 192 Commit point reached - logical record COUNT 256 Commit point reached - logical record COUNT 320 Commit point reached - logical record COUNT 384 Commit point reached - logical record COUNT 448 Commit point reached - logical record COUNT 512 Commit point reached - logical record COUNT 576 Commit point reached - logical record COUNT 640 Commit point reached - logical record COUNT 664 |
第一次执行导入,检查表的空间占用:
SQL> SELECT TABLE_NAME, a.segment_name, bytes/1024/1024 FROM user_segments a, user_lobs b WHERE b.segment_name = a.segment_name ORDER BY 1; TABLE_NAME SEGMENT_NAME BYTES/1024/1024 ------------------------------ ------------------------------ --------------- T_LOAD_4M SYS_LOB0000062585C00004$$ 1088 T_LOAD_4M_SF SYS_LOB0000062641C00004$$ 1220.1875 |
其中T_LOAD_4M是LOB没有采用SECUREFILE方式保存的普通表。这个表每次执行TRUNCATE方式的SQLLDR加载后,空间并不会发生变化,但是T_LOAD_4M_SF随着执行SQLLDR次数的增加,空间占用的情况分别变为:
SQL> SELECT TABLE_NAME, a.segment_name, bytes/1024/1024 FROM user_segments a, user_lobs b WHERE b.segment_name = a.segment_name ORDER BY 1; TABLE_NAME SEGMENT_NAME BYTES/1024/1024 ------------------------------ ------------------------------ --------------- T_LOAD_4M SYS_LOB0000062585C00004$$ 1088 T_LOAD_4M_SF SYS_LOB0000062641C00004$$ 1348.1875 SQL> SELECT TABLE_NAME, a.segment_name, bytes/1024/1024 FROM user_segments a, user_lobs b WHERE b.segment_name = a.segment_name ORDER BY 1; TABLE_NAME SEGMENT_NAME BYTES/1024/1024 ------------------------------ ------------------------------ --------------- T_LOAD_4M SYS_LOB0000062585C00004$$ 1088 T_LOAD_4M_SF SYS_LOB0000062641C00004$$ 1540.1875 SQL> SELECT TABLE_NAME, a.segment_name, bytes/1024/1024 FROM user_segments a, user_lobs b WHERE b.segment_name = a.segment_name ORDER BY 1; TABLE_NAME SEGMENT_NAME BYTES/1024/1024 ------------------------------ ------------------------------ --------------- T_LOAD_4M SYS_LOB0000062585C00004$$ 1088 T_LOAD_4M_SF SYS_LOB0000062641C00004$$ 1732.125 |
除了第一次加载空间增长了128M外,以后每次加载都会导致表空间增长192M。而同样的操作并不会导致BASICFILE方式的LOB表。
导致这个现象的原因除了SECUREFILE存储方式外,也与SQLLDR的TRUNCATE导入方式有关,SQLLDR的TRUNCATE只是为了清空数据,由于随后还要执行导入,因此没有必要回收分配的空间,因此这个TRUNCATE语句会保留现有的空间,在加上SECUREFILE的特殊性,导致了每次加载LOB都使得表的空间不断的增长。
而如果尝试直接执行TRUNCATE TABLE语句,则会使得表的高水位线被清空,表的大小恢复到0。虽然这里存在一定的空间泄漏,但是对于实际生产环境中,这种TRUNCATE的SQLLDR方式应该极为罕见,因此并不会导致什么危害。
One Response to TRUNCATE模式SQLLDR导致SECUREFILE的LOB空间不断增长