sql中如何释放大数据量的lob字段空间,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
sql> create tablespace ts_lob datafile '/u01/app/oracle/oradata/DBdb/ts_lob.dbf' size 500m autoextend off;
Tablespace created.
--scott用户创建测试表lob1:
sql> grant dba to scott;
Grant succeeded.
sql> conn scott/tiger;
Connected.
sql> create table lob1(line number,text clob) tablespace ts_lob;
Table created.
sql> insert into lob1 select line,text from dba_source;
637502 rows created.
sql> insert into lob1 select * from lob1;
637502 rows created.
sql> select count(*) from lob1;
COUNT(*)
----------
1275004
sql> commit;
Commit complete.
--查询表大小(包含表和lob字段)
select (select nvl(sum(s.bytes/1024/1204), 0) -- the table segment size
from dba_segments s
where s.owner = upper('SCott')
and (s.segment_name = upper('LOB1'))) +
(select nvl(sum(s.bytes/1024/1024), 0) -- the lob segment size
from dba_segments s, dba_lobs l
where s.owner = upper('SCott')
and (l.segment_name = s.segment_name and
l.table_name = upper('LOB1') and
l.owner = upper('SCott'))) +
(select nvl(sum(s.bytes/1024/1024), 0) -- the lob index size
from dba_segments s, dba_indexes i
where s.owner = upper('SCott')
and (i.index_name = s.segment_name and
i.table_name = upper('LOB1') and index_type = 'LOB' and
i.owner = upper('SCott'))) "total_table_size_M"
FROM DUAL;
total_table_size_M
------------------
239.966154
--查询表大小(不包含lob字段)
col SEGMENT_NAME for a30
col PARTITION_NAME for a30
sql> select OWNER,SEGMENT_NAME,PARTITION_NAME,BYTES/1024/1024 M from dba_segments where segment_name='LOB1' and owner='SCott';
OWNER SEGMENT_NAME PARTITION_NAME M
------------------------------ ------------------------------ ------------------------------ ----------
SCott LOB1 208
--查询表大小(只包含lob字段)
set lines 200 pages 999
col owner for a15
col TABLE_NAME for a20
col COLUMN_NAME for a30
col SEGMENT_NAME for a30
select a.owner,
a.table_name,
a.column_name,
b.segment_name,
b.segment_type,
ROUND(b.BYTES / 1024 / 1024)
from dba_lobs a, dba_segments b
where a.segment_name = b.segment_name
and a.owner = 'SCott'
and a.table_name = 'LOB1'
union all
select a.owner,
a.table_name,
a.column_name,
b.segment_name,
b.segment_type,
ROUND(b.BYTES / 1024 / 1024)
from dba_lobs a, dba_segments b
where a.index_name = b.segment_name
and a.owner = 'SCott'
and a.table_name = 'LOB1';
OWNER TABLE_NAME COLUMN_NAME SEGMENT_NAME SEGMENT_TYPE ROUND(B.BYTES/1024/1024)
--------------- -------------------- ------------------------------ ------------------------------ ------------------ ------------------------
SCott LOB1 TEXT SYS_LOB0000089969C00002$$ LOBSEGMENT 63
SCott LOB1 TEXT SYS_IL0000089969C00002$$ LOBINDEX 0
--查询ts_lob表空间的表大小排行
sql> select * from (select SEGMENT_NAME,sum(bytes)/1024/1024 sx from dba_segments
where tablespace_name='TS_LOB' group by segment_name )
order by sx desc;
SEGMENT_NAME SX
------------------------------ ----------
LOB1 208
SYS_LOB0000089969C00002$$ 63
SYS_IL0000089969C00002$$ .0625
--查询lob字段SCott_LOB0000089963C00002$$ 、SCott_IL0000089963C00002$$:
sql> col object_name for a30
sql> select OWNER,OBJECT_NAME,OBJECT_TYPE from dba_objects where OBJECT_NAME in('SYS_LOB0000089969C00002$$','SYS_IL0000089969C00002$$');
OWNER OBJECT_NAME OBJECT_TYPE
--------------- ------------------------------ -------------------
SCott SYS_IL0000089969C00002$$ INDEX
SCott SYS_LOB0000089969C00002$$ LOB
sql> select OWNER,TABLE_NAME,COLUMN_NAME,SEGMENT_NAME,TABLESPACE_NAME,INDEX_NAME from dba_lobs where segment_name in('SYS_LOB0000089969C00002$$','SYS_IL0000089969C00002$$');
OWNER TABLE_NAME COLUMN_NAME SEGMENT_NAME TABLESPACE_NAME INDEX_NAME
--------------- -------------------- ------------------------------ ------------------------------ ------------------------------ ------------------------------
SCott LOB1 TEXT SYS_LOB0000089969C00002$$ TS_LOB SYS_IL0000089969C00002$$
sql>
sql> select SEGMENT_NAME,bytes /1024/1024 sx from dba_segments where tablespace_name='TS_LOB' and SEGMENT_NAME in('SYS_LOB0000089969C00002$$','SYS_IL0000089969C00002$$');
SEGMENT_NAME SX
------------------------------ ----------
SYS_LOB0000089969C00002$$ 63
SYS_IL0000089969C00002$$ .0625
一、先试着删除lob字段:
sql> alter table scott.lob1 drop (text);
Table altered.
sql> select SEGMENT_NAME,bytes /1024/1024 sx from dba_segments where tablespace_name='TS_LOB' and SEGMENT_NAME in('SYS_LOB0000089969C00002$$','SYS_IL0000089969C00002$$');
no rows selected
sql> select * from (select SEGMENT_NAME,sum(bytes)/1024/1024 sx from dba_segments where tablespace_name='TS_LOB' group by segment_name ) order by sx desc;
SEGMENT_NAME SX
------------------------------ ----------
LOB1 208
发现删除lob字段可以释放表空间。
--再次添加LOB字段:
sql> alter table scott.lob1 add (text clob);
Table altered.
sql> select * from (select SEGMENT_NAME,sum(bytes)/1024/1024 sx from dba_segments where tablespace_name='TS_LOB' group by segment_name ) order by sx desc;
SEGMENT_NAME SX
------------------------------ ----------
LOB1 208
SYS_LOB0000089969C00002$$ .0625
SYS_IL0000089969C00002$$ .0625
二、再次插入数据:
sql> insert into scott.lob1 select LINE,text from dba_source;
637502 rows created.
sql> insert into scott.lob1 select LINE,text from dba_source;
637502 rows created.
sql> commit;
Commit complete.
sql> select * from (select SEGMENT_NAME,sum(bytes)/1024/1024 sx from dba_segments where tablespace_name='TS_LOB' group by segment_name ) order by sx desc;
SEGMENT_NAME SX
------------------------------ ----------
LOB1 208
SYS_LOB0000089969C00002$$ 63
SYS_IL0000089969C00002$$ .0625
--接着试着truncate表LOB1
sql> truncate table scott.lob1;
Table truncated.
sql> select * from (select SEGMENT_NAME,sum(bytes)/1024/1024 sx from dba_segments where tablespace_name='TS_LOB' group by segment_name ) order by sx desc;
SEGMENT_NAME SX
------------------------------ ----------
LOB1 .0625
SYS_LOB0000089969C00002$$ .0625
SYS_IL0000089969C00002$$ .0625
truncate表也可以释放lob字段数据;
三、再次插入数据:
sql> insert into scott.lob1 select LINE,text from dba_source;
637502 rows created.
sql> insert into scott.lob1 select LINE,text from dba_source;
637502 rows created.
sql> commit;
Commit complete.
sql>
sql> select * from (select SEGMENT_NAME,sum(bytes)/1024/1024 sx from dba_segments where tablespace_name='TS_LOB' group by segment_name ) order by sx desc;
SEGMENT_NAME SX
------------------------------ ----------
LOB1 184
SYS_LOB0000089969C00002$$ 63
SYS_IL0000089969C00002$$ .0625
使用delete方式删除数据,实际上物理块还是被占用,高水位没有下降。
sql> delete scott.lob1;
1275004 rows deleted.
sql>
sql> select * from (select SEGMENT_NAME,sum(bytes)/1024/1024 sx from dba_segments where tablespace_name='TS_LOB' group by segment_name ) order by sx desc;
SEGMENT_NAME SX
------------------------------ ----------
LOB1 184
SYS_LOB0000089969C00002$$ 63
SYS_IL0000089969C00002$$ .75
sql> select count(*) from scott.lob1;
COUNT(*)
----------
0
sql> truncate table scott.lob1;
Table truncated.
sql> select * from (select SEGMENT_NAME,sum(bytes)/1024/1024 sx from dba_segments where tablespace_name='TS_LOB' group by segment_name ) order by sx desc;
SEGMENT_NAME SX
------------------------------ ----------
LOB1 .0625
SYS_LOB0000089969C00002$$ .0625
SYS_IL0000089969C00002$$ .0625
结论:在删除lob字段的大数据量时,可以采用重建表(CTAS)、删除lob字段再重建alter table table_name drop (column)、导出导入(只导出元数据)、或者直接truncate全表删除全表(包括lob)降低高水位。
看完上述内容,你们掌握sql中如何释放大数据量的lob字段空间的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注编程之家行业资讯频道,感谢各位的阅读!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。