LOB列之-如何降低高水位,及需要关注点

最近客户反馈他们delete了包含LOB列的表,通过shrink space 无法降低LOB列的高水位,无法回收空间,进行了测试。

环境说明:
1、数据库版本11.2.0.4.0
2、DB_SECUREFILE=PERMITTED(允许创建SecureFiles(默认值))

测试目的:

通过对表进行delete操作后,想通过move和shrink降低表和LOB列的高水位。

结论:
1、当LOB类型为SecureFile时,通过对表进行shrink 操作,表高水位可以降低,但是LOB列高水位无法降低
2、当LOB类型为BasicFiles时,通过对表进行shrink 操作,表高水位可以降低,LOB列高水位也可以降低。
3、当LOB类型为SecureFile时,通过对表进行move 操作,表高水位可以降低,但是LOB列高水位无法降低,需要通过MOVE LOB列进行操作降低
4、当LOB类型为BasicFiles时,通过对表进行move 操作,表高水位可以降低,但是LOB列高水位无法降低,需要通过MOVE LOB列进行操作降低
5、不管怎么样,LOB列的高水位无法降低,可以通过单独通过move lob列来进行降低高水位。

6、在对LOB列单独MOVE的时候,LOB列的索引不会失效,但是非LOB列的索引会失效!生产上一定要慎重,同时如果做的话,别忘记观察索引状态,及时rebuild索引

以下是详细的测试过程:
=====================    先进行shrink操作测试       ================
1、创建SECUREFILES 和 BASICFILES类型LOB表

--创建SECUREFILE类型LOB表
CREATE TABLE SECUREFILES_TAB (
     id         NUMBER,
     clob_data  CLOB
   )
   LOB(clob_data) STORE AS SECUREFILE;
   
--创建BASICFILE类型LOB表(不加LOB(clob_data) STORE AS BASICFILE 这段默认就是BASICFILE类型)
CREATE TABLE BASICFILES_TAB(
     id         NUMBER,
     clob_data  CLOB
   );


2、创建索引(观察索引失效情况),生产上,可以先考虑插入数据,再创建索引,提升插入效率
create index ind_SECUREFILES_TAB_id on SECUREFILES_TAB(id);
create index ind_BASICFILES_TAB_id on BASICFILES_TAB(id);

SQL> create index ind_SECUREFILES_TAB_id on SECUREFILES_TAB(id);
create index ind_BASICFILES_TAB_id on BASICFILES_TAB(id);

Index created.

SQL> 
Index created.

SQL> 


3、插入数据

SQL> DECLARE
  2      l_clob CLOB := RPAD('X',10000, 'X');
  3    BEGIN
  4  for i IN 1..1000 LOOP
  5        INSERT INTO SECUREFILES_TAB VALUES (i, l_clob);
  6      END LOOP;
  7      COMMIT;
  8  for i IN 1..1000 LOOP
  9        INSERT INTO BASICFILES_TAB VALUES (i, l_clob);
 10      END LOOP;
 11      COMMIT;
 12     END;
 13     /  

PL/SQL procedure successfully completed.

4、检查数据
SQL> SQL> 
SQL> select count(*) from SECUREFILES_TAB;

  COUNT(*)
----------
      1000

SQL> select count(*) from BASICFILES_TAB;

  COUNT(*)
----------
      1000  

5、检查表对应的LOB列

SQL> set linesize 300
col COLUMN_NAME for a20

6、检查索引状态,都是有效的
select owner,index_name,table_name,status from dba_indexes where table_name in ('SECUREFILES_TAB','BASICFILES_TAB');

7、查看表和LOB列大小
SQL> SELECT segment_name, bytes
  2  FROM   dba_segments
  3  WHERE  segment_name IN ('SECUREFILES_TAB','BASICFILES_TAB','SYS_LOB0000028976C00002$$','SYS_LOB0000028973C00002$$');

 
8、对表进行delete 操作
SQL>

 delete from SECUREFILES_TAB where id>10;
delete from BASICFILES_TAB where id>10;

990 rows deleted.

SQL> 
990 rows deleted.

9、delete 后再次查看表和LOB列大小,没有变化
SQL> SELECT segment_name, bytes
  2  FROM   user_segments
  3  WHERE  segment_name IN ('SECUREFILES_TAB','BASICFILES_TAB','SYS_LOB0000028976C00002$$','SYS_LOB0000028973C00002$$');

 
10、对表进行shrink操作

SQL>

ALTER TABLE YJB.SECUREFILES_TAB ENABLE ROW MOVEMENT;
ALTER TABLE YJB.SECUREFILES_TAB SHRINK SPACE CASCADE;

ALTER TABLE YJB.BASICFILES_TAB ENABLE ROW MOVEMENT;
ALTER TABLE YJB.BASICFILES_TAB SHRINK SPACE CASCADE;

Table altered.

SQL> 
Table altered.

SQL> SQL> 
Table altered.

SQL> 

Table altered.


11、查看对表做shrink后,表和LOB列大小

发现
   1、表的大小都变小了,即高水位降低了
   2、BASICFILE的LOB列的大小也变小了,
但是LOB列类型为SECUREFILE的LOB,大小保持不变。
   
SQL> SELECT segment_name, bytes
  2  FROM   dba_segments
  3  WHERE  segment_name IN ('SECUREFILES_TAB','BASICFILES_TAB','SYS_LOB0000028976C00002$$','SYS_LOB0000028973C00002$$');

 
12、查看索引状态,通过shrink操作后,都是有效的,主要是由于shrink会自动维护索引。
SQL> select owner,index_name,table_name,status from dba_indexes where table_name in ('SECUREFILES_TAB','BASICFILES_TAB');


13、对无法降低高水位的LOB列进行单独MOVE操作
SQL> alter table SECUREFILES_TAB move lob(clob_data) store as  (tablespace users);

Table altered.

=======

14、再次查看LOB列的高水位情况,发现已经下降,同时回收了空间
SQL> SELECT segment_name, bytes
  2  FROM   user_segments
  3  WHERE  segment_name IN ('SECUREFILES_TAB','BASICFILES_TAB','SYS_LOB0000028890C00002$$','SYS_LOB0000028893C00002$$');

15、再次检查索引,LOB列的索引状态正常,但是发现非LOB列的索引反而变成:失效状态这个坑,大家生产上,还是要特别注意。

 16、通过rebuild 进行重建后,id列索引恢复正常。

SQL> alter index IND_SECUREFILES_TAB_ID rebuild;

=====================    然后进行MOVE操作测试       ================

1、创建SECUREFILES 和 BASICFILES类型LOB表

创建SECUREFILE类型LOB表
SQL> CREATE TABLE SECUREFILES_TAB (
  2       id         NUMBER,
  3       clob_data  CLOB
  4     )
  5     LOB(clob_data) STORE AS SECUREFILE;
   
--创建BASICFILE类型LOB表
CREATE TABLE BASICFILES_TAB(
     id         NUMBER,
     clob_data  CLOB
   )
   LOB(clob_data) STORE AS BASICFILE;

Table created.

SQL> SQL> SQL>   2    3    4    5  
Table created.


 

2、创建索引
create index ind_SECUREFILES_TAB_id on SECUREFILES_TAB(id);
create index ind_BASICFILES_TAB_id on BASICFILES_TAB(id);

3、插入数据。

SQL> SQL> SQL> SQL> DECLARE
  2        l_clob CLOB := RPAD('X',10000, 'X');
  3      BEGIN
  4    for i IN 1..1000 LOOP
  5          INSERT INTO SECUREFILES_TAB VALUES (i, l_clob);
  6        END LOOP;
  7        COMMIT;
  8    for i IN 1..1000 LOOP
  9          INSERT INTO BASICFILES_TAB VALUES (i, l_clob);
 10        END LOOP;
 11        COMMIT;
 12       END;
 13       /  

PL/SQL procedure successfully completed.

4、查看数据量。

SQL> select count(*) from SECUREFILES_TAB;
select count(*) from BASICFILES_TAB;

  COUNT(*)
----------
      1000

SQL> 
  COUNT(*)
----------
      1000

SQL> 

5、查看表的LOB列

SQL> set linesize 300
col COLUMN_NAME for a20
select owner,table_name,column_name,segment_name,INDEX_NAME,tablespace_name,COMPRESSION,DEDUPLICATION,SECUREFILE from dba_lobs where table_name in ('SECUREFILES_TAB','BASICFILES_TAB');

6、检查索引状态,都是有效的
SQL> SQL> select owner,index_name,table_name,status from dba_indexes where table_name in ('SECUREFILES_TAB','BASICFILES_TAB');

7、检查表、索引大小

SELECT segment_name, bytes
FROM   dba_segments
WHERE  segment_name IN ('SECUREFILES_TAB','BASICFILES_TAB','SYS_LOB0000029137C00002$$','SYS_LOB0000029134C00002$$');

8、对表进行delete 操作,表和LOB高水位都没有下降。

delete from SECUREFILES_TAB where id>10;
delete from BASICFILES_TAB where id>10;

SELECT segment_name, bytes
FROM   dba_segments
WHERE  segment_name IN ('SECUREFILES_TAB','BASICFILES_TAB','SYS_LOB0000029137C00002$$','SYS_LOB0000029134C00002$$');


9、MOVE表后,表和索引高水位下降,但是两种类型的LOB对象高水位没有降低
SQL> alter table SECUREFILES_TAB move;
alter table BASICFILES_TAB move;


SQL> SELECT segment_name, bytes
FROM   dba_segments
WHERE  segment_name IN ('SECUREFILES_TAB','BASICFILES_TAB','SYS_LOB0000029137C00002$$','SYS_LOB0000029134C00002$$');

 10、LOB列索引未失效,但是非LOB列的索引失效了(shrink这点就比move要强)。
SQL> select owner,index_name,table_name,status from dba_indexes where table_name in ('SECUREFILES_TAB','BASICFILES_TAB');


11、单独对LOB列进行move操作,可以看到LOB列的高水位已经降低
SQL> 
SQL> alter table SECUREFILES_TAB move lob(clob_data) store as  (tablespace users);
alter table BASICFILES_TAB move lob(clob_data) store as  (tablespace users);

SQL> SELECT segment_name, bytes
  2     FROM   dba_segments
  3     WHERE  segment_name IN ('SECUREFILES_TAB','BASICFILES_TAB','SYS_LOB0000028908C00002$$','SYS_LOB0000028911C00002$$','IND_BASICFILES_TAB_ID','IND_SECUREFILES_TAB_ID');

12、最后别忘记把失效的索引rebuild.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值