暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

Oracle库中删除LOB数据

原创 董小姐 2024-04-11
1000

关键步骤:

检查数据库中存在的LOB数据

将LOB字段设置为空的LOB值,从而实现删除LOB数据的效果(使用empty_blob()或者empty_clob()函数)。在具体操作时,可以选择性地使用WHERE子句来删除特定条件下的LOB数据。

实验背景

同事在巡检RAC业务库时发现共享存储剩余空间仅剩余200G左右了,问是否可以查出来LOB字段的表并统计大小,删除开发指定的LOB字段数据以释放空间。

数据类型说明

varchar2类型

在Oracle数据库存储的字符数据一般是用VARCHAR2。VARCHAR2既分PL/SQL Data Types中的变量类型,也分Oracle Database中的字段类型,不同场景的最大长度不同。

在Oracle Database中,VARCHAR2 字段类型,最大值为4000;PL/SQL中 VARCHAR2 变量类型,最大字节长度为32767。

当 VARCHAR2 容纳不下需要存储的信息时,就需要用Oracle的大数据类型LOB( Large Object,大型对象)。

LOB类型

在Oracle中,LOB是一种用于存储大型二进制或字符数据的数据类型。LOB(Large Object,大型对象)类型的字段现在用得越来越多了。因为这种类型的字段,容量大(最多能容纳4GB的数据),且一个表中可以有多个这种类型的字段,很灵活,适用于数据量非常大的业务领域(如图象、档案等)。

LOB类型分为BLOB和CLOB两种:BLOB即二进制大型对象(Binary Large Object),适用于存贮非文本的字节流数据(如程序、图象、影音等)。通常像图片、文件、音乐等信息就用BLOB字段来存储,先将文件转为二进制再存储进去。

CLOB,即字符型大型对象(Character Large Object),则与字符集相关,适于存贮文本型的数据(如历史档案、大部头著作等),不支持宽度不等的字符集。虽然CLOB能解决VARCHAR2字符大小的限制,但是我们的DBA们都不建议用这些来处理,可能效率问题吧,大的文件应该放在服务器上,然后Database中存响应地址即可。可存储的最大大小为4G字节。

特别说明:

对表上的lob字段是单独存储的,所以使用segment_name = 表名 的时候,只能统计非 lob 字段的数据大小,无法统计上lob字段的。正确的计算方式应该是:dba_segments中表占用的空间+LOB segments占的空间+ LOB 的索引。

LOB数据常用操作

创建LOB业务表

创建含BLOB业务表

create table scott.blob_temp
(
  name      VARCHAR2(200),
  age       NUMBER,
  temp_clob BLOB
);

创建含CLOB业务表

创建表(使用sql或者直接在PL/SQL客户端创建),字段类型CLOB

create table scott.temp
(
  name      VARCHAR2(200),
  age       NUMBER,
  temp_clob CLOB
);

增删改查

含BLOB业务表插入数据

示例1:将内容转换成二进制进行插入

--示例1
INSERT INTO scott.blob_temp VALUES ('1',19,rawtohex('内容'));
commit;

insert into scott.blob_temp select * from scott.blob_temp;

含CLOB业务表插入数据

普通方式增删改查

普通插入操作会因为Oracle的隐式转换,默认把字符串转换成varchar2类型,一旦字符串内容超过varchar2的最大限度就会报会报ora-01704(字符串太长)错误。

--插入数据
insert into scott.temp values('1',12,'这是一相故顶真参压顶地');
commit;

--普通查询
col name for a30
SELECT t.name, t.temp_clob FROM scott.temp t;

NAME			       TEMP_CLOB
------------------------------ --------------------------------------------------------------------------------
1			       这是一相故顶真参压顶地
1			       这是一相故顶真参压顶地

dbms_lob方式增删改查

--使用PL/SQL语法,采取绑定变量的方式解决,而不是直接拼接SQL
DECLARE 
       V_LANG CLOB := '待插入的海量字符串';     
       V_UPDATE CLOB := '更新的海量字符串';
BEGIN
  insert into scott.temp values('1',3,'新疆自治区的第一旅行');        --增加
  UPDATE scott.temp t SET t.temp_clob = 'V_UPDATE' WHERE rownum = 1;  --修改
  SELECT t.NAME, dbms_lob.substr(t.temp_clob) FROM scott.temp t;    --查询  将CLOB转成字符类型
  DELETE scott.temp t WHERE rownum = 1;                             --按列删除  
  COMMIT;
END;
/

dbms_lob 方法总结:

dbms_lob.createtemporary(V_SQL,true);     --创建一个临时clob,用来存储拼接的sql
dbms_lob.write(v_SQL,'写入信息');          --写入操作
dbms_lob.append(v_SQL,',');               --拼接clob
dbms_lob.substr(v_SQL);                   --截取clob,不传参数就是全部读取
dbms_lob.freetemporary(v_SQL);            --释放clob

检查LOB数据

删除LOB数据之前,首先需要检查数据库中存在的LOB数据。

--获取LOB字段的名称、拥有者、大小
col segment_name for a50
set linesize 999 pagesize 999
SELECT owner,SEGMENT_NAME, ROUND(SUM(BYTES / 1024 / 1024 / 1024), 2) G
  FROM DBA_SEGMENTS
 WHERE SEGMENT_NAME IN
       (SELECT TABLE_NAME FROM DBA_TAB_COLUMNS WHERE DATA_TYPE = 'BLOB')
       and owner='SCOTT'
 GROUP BY owner,SEGMENT_NAME
 ORDER BY 2 DESC;

 或
col tablespace_name for a40
col column_name for a40
SELECT B.TABLE_NAME,
      B.COLUMN_NAME,
	  A.TABLESPACE_NAME,
      A.SEGMENT_NAME,
      a.SEGMENT_TYPE,
      ROUND(SUM(A.BYTES / 1024 / 1024 / 1024), 2) G
 FROM DBA_SEGMENTS A
 LEFT JOIN DBA_LOBS B
   ON A.OWNER = B.OWNER
  AND A.SEGMENT_NAME = B.SEGMENT_NAME
  where A.OWNER ='SCOTT'
--WHERE B.SEGMENT_NAME = 'SYS_LOB0000026212C00002$$'
HAVING ROUND(SUM(A.BYTES / 1024 / 1024 / 1024), 2) >1
GROUP BY B.TABLE_NAME, B.COLUMN_NAME, A.SEGMENT_NAME,a.SEGMENT_TYPE,A.TABLESPACE_NAME
order by ROUND(SUM(A.BYTES / 1024 / 1024 / 1024), 2) ;

上述查询语句将返回包含LOB字段的表名和对应的LOB字段名。通过这个查询结果,我们可以确认数据库中存在哪些LOB数据。

删除LOB数据

empty_blob()或empty_clob()函数方式

当LOB数据不再需要时,可能需要将其从数据库中删除以释放存储空间。

在删除LOB数据之前,需要明确删除的是哪个表中的LOB数据以及对应的LOB字段名称。假设要删除的表名为my_table,LOB字段名称为my_lob,可以使用如下的SQL语句来删除LOB数据:

UPDATE my_table
SET my_lob = empty_blob() -- 对于BLOB字段使用empty_blob(),对于CLOB字段使用empty_clob()
WHERE <some condition>; -- 可选,选择性地删除特定的LOB数据

在上述的SQL语句中,将要删除的LOB字段设置为空的LOB值,从而实现删除LOB数据的效果。需要注意的是,可以选择性地使用WHERE子句来删除特定条件下的LOB数据,如果不指定条件,则会删除表中所有的LOB数据。

另外,如果要删除的是CLOB字段而不是BLOB字段,那么应该使用empty_clob()函数来将CLOB字段设置为空的CLOB值。

函数方式并不会释放空间,查询依然是原来占用空间大小。

tuncate方式

直接删除

示例

--确认表中存在的LOB字段
set linesize 999
SELECT table_name, column_name ,data_type
FROM user_tab_cols 
WHERE table_name = 'TEMP';

TABLE_NAME						     COLUMN_NAME						  DATA_TYPE
------------------------------------------------------------ ------------------------------------------------------------ --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TEMP							     NAME							        VARCHAR2
TEMP							     AGE							        NUMBER
TEMP							     TEMP_CLOB							  CLOB

--查询数据
SQL> col name for a30
SQL> select * from temp;

NAME				      AGE TEMP_CLOB
------------------------------ ---------- --------------------------------------------------------------------------------
1				       12 这是一相故顶真参压顶地

--删除temp表中的LOB数据
UPDATE temp
SET TEMP_CLOB = empty_clob()
WHERE name='1';

如果是删除blob内容,将empty_clob()更改为empty_blob()

案例1

最近,某个数据接口项目上ORACLE数据库的使用空间越来越大,查看一下数据库中哪个数据表的数据量的大小,以便进行有针对性的处理.

查看Oracle中表空间及表数据大小

--查看数据库中有哪些用户
set lin1000 pagesize 999
select username,default_tablespace,temporary_tablespace from dba_users where username not in ('SYS','SYSTEM','HR','OUTLN','MGMT_VIEW','FLOWS_FILES','MDSYS','ORDSYS','EXFSYS','DBSNMP','WMSYS','APPQOSSYS','APEX_030200','OWBSYS_AUDIT','ORDDATA','CTXSYS','ANONYMOUS','SYSMAN','XDB','ORDPLUGINS','OWBSYS','SI_INFORMTN_SCHEMA','OLAPSYS','SCOTT','ORACLE_OCM','XS$NULL','BI','PM','MDDATA','IX','SH','DIP','OE','APEX_PUBLIC_USER','SPATIAL_CSW_ADMIN_USR','SPATIAL_WFS_ADMIN_USR');

--查看Oracle中表空间及表数据大小
SELECT OWNER,SEGMENT_NAME,
       (SUM(BYTES) / 1024 / 1024 / 1024)  AS TABLE_SIZE
  FROM DBA_EXTENTS where owner in ('TOPICIS','TOPICPSP')
 GROUP BY OWNER,SEGMENT_NAME
 ORDER BY owner,TABLE_SIZE DESC;

分析数据最大的对象

从返回的结果看,有一个segment名为"SYS_LOB0000090035C00005$$"的对象占用了大量的空间,这种带有SYS_LOB***即LOB(BLOB和CLOB)对象占用数据库的空间名称。

定位数据最大的对象对应的表

根据segment_name,就可以从 dba_lobs 表里查到是哪个表,哪个字段,具体的SQL如下:

 SELECT * FROM DBA_LOBS WHERE SEGMENT_NAME LIKE 'SYS_LOB0000164649C00003$$';

可以发现是LOG_MQLISTENERINFO这个表里存在的Bolb类型LOGINFO存有大数据,占用了20.03GB的空间。

查看表结构

清理数据

--删除temp表中的LOB数据
UPDATE LOG_MQLISTENERINFO
SET LOGINFO = empty_clob();
commit;

使用empty_clob()后空间并不会缩小,查询后大小还是原来大小

--启用行迁移
alter table REG_BUSMAIINF_XMLDATA enable row movement; 

--释放空间方法
方法1:收缩表
ALTER TABLE REG_BUSMAIINF_XMLDATA SHRINK SPACE CASCADE;

方法2:truncate表
truncate table TOPICIS. REG_BUSMAIINF_XMLDATA;

--查询对象大小,已变小
SELECT OWNER,SEGMENT_NAME,
       (SUM(BYTES) / 1024 / 1024 / 1024)  AS TABLE_SIZE
  FROM DBA_EXTENTS where owner in ('TOPICIS','TOPICPSP') and segment_name='SYS_LOB0000095888C00003$$'
 GROUP BY OWNER,SEGMENT_NAME
 ORDER BY owner,TABLE_SIZE DESC;
--关闭行迁移 alter table REG_BUSMAIINF_XMLDATA disable row movement;

参考链接:https://blog.csdn.net/qq_20197983/article/details/81487411

最后修改时间:2024-04-15 17:58:15
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论