文章結構如下:
1.背景:
生產上查詢那些大表然后進行清理,然而發現有SYS_LOB0000093441C00002$$這中表段占用30G(只保留一個月,如果保留更久會更大)。
2.LOB介紹
Oracle 數據庫中varchar2只能值為4000,PL/SQL中 VARCHAR2 變量類型,字節長度為32767,針對 VARCHAR2 滿足不了我們的需要時,Oracle就提出了大數據類型LOB( Large Object,大對象)。
Oarcle中的LOB類型:
在Oracle中,LOB(Large Object,大型對象)類型的字段現在用得越來越多了。因為這種類型的字段,容量大(最多能容納4GB的數據),且一個表中可以有多個這種類型的字段,很靈活,適用於數據量非常大的業務領域(如圖象、檔案等)。
LOB類型分為BLOB和CLOB兩種:BLOB即二進制大型對象(Binary Large Object),適用於存貯非文本的字節流數據(如程序、圖象、影音等)。
而CLOB,即字符型大型對象(Character Large Object),則與字符集相關,適於存貯文本型的數據(如歷史檔案、大部頭著作等)。
3.LOB大字段的清理(或者處理辦法)
SELECT SEGMENT_NAME, ROUND(SUM(BYTES / 1024 / 1024 / 1024), 2) G
FROM DBA_SEGMENTS
WHERE SEGMENT_NAME IN
(SELECT TABLE_NAME FROM USER_TAB_COLUMNS WHERE DATA_TYPE = 'CLOB')
GROUP BY SEGMENT_NAME
ORDER BY 2 DESC;
SELECT SEGMENT_NAME, ROUND(SUM(BYTES / 1024 / 1024 / 1024), 2) G
FROM DBA_SEGMENTS
--WHERE SEGMENT_NAME IN
-- (SELECT TABLE_NAME FROM USER_TAB_COLUMNS WHERE DATA_TYPE = 'CLOB')
GROUP BY SEGMENT_NAME
ORDER BY 2 DESC;
SELECT B.TABLE_NAME,
B.COLUMN_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 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;
經查看,PAY_LOG_DETAILS表這一列CONTENT建的clob,其中大對象單獨存放在SYS_LOB0000093441C00002$$ 這個段中,LOBSEGMENT保存了lob列的真正數據,會非常大30G,並且獨立於原始表存在。
1) 清理建的lob列的表
如果需要清理,可以truncate 該PAY_LOG_DETAILS表,或者drop不需要的分區(如果是分區表)
2) shrink的lob列的表
生產上如果使用表頻繁的DML操作不建議shrink,會卡死,引起嚴重的業務后果
比如說在你大量的刪除PAY_LOG_DETAILS后(高水位沒有下降),需要執行收縮,收縮的時候建議在不要再業務高峰期(否則可能引起很大的性能問題)
Shrink對應的表語句如下:
注意:由於在線上,不能進行有表鎖的操作,所以我並沒有采用這種辦法
alter table TABLE_NAME enable ROW MOVEMENT;--啟動行移動功能
alter table TABLE_NAME shrink space compact; --只整理碎片 不回收空間
-- 重置高水位,此時不能有DML操作
alter table TABLE_NAME shrink space; --整理碎片並回收空間,並調整水位線。業務少時執行
alter table TABLE_NAME disable ROW MOVEMENT;--關閉行移動
3) ASK tom 大佬提到db_securefile,外部表
我自己也只是掃了一眼該回復,經過查看11g允許創建SecureFiles(默認值)PERMITTED模式,他的思想是遷移到SecureFiles文件或者是我們熟知的外部表那種(直接存在外部表里管理更簡單)
提供網頁如下:
https://asktom.oracle.com/pls/apex/asktom.search?tag=reclaimreuse-lob-space
4. LOB建議
可能對一般的oracle dba或者其它人員,來說,並不是所有東西都要存入數據庫,再設計表結構的時候(叫所謂的建模吧!),就應該考慮是否應該存在大字段,需要滿足什么功能,好不好管理,對數據集的性能影響有多大?
個人不太建議在數據庫中使用大對象,可以使用外部表(管理方便,更加的簡單粗暴),大對象所對應的表進行DML語句是,需要更大的開銷,影響性能;比如,可以考慮做一個文件服務器,把需要的大對象按照一定的格式(如時間格式)存成文件,數據庫中存放指定的地址就行,這樣可以大大提高性能。
5.可以提供的資料
https://asktom.oracle.com/pls/apex/asktom.search?tag=reclaimreuse-lob-space
https://connor-mcdonald.com/2015/07/03/continuous-delivery-moving-to-securefile/
http://www.oracle.com/technetwork/articles/sql/11g-securefiles-084075.html