關於Oracle資料庫LOB大欄位總結

2019-08-28     波波說運維

概述

在ORACLE資料庫中,DBA_OBJECTS視圖中OBJECT_TYPE為LOB的對象是什麼東西呢?其實OBJECT_TYPE為LOB就是大對象(LOB),它指那些用來存儲大量數據的資料庫欄位。

Oracle 11gR2 文檔:

http://download.oracle.com/docs/cd/E11882_01/appdev.112/e18294/adlob_tables.htm#ADLOB45267


一、LOB 分類

LOB大對象主要是用來存儲大量數據的資料庫欄位,在Oracle 9iR2 中LOB的最大容量是4G,Oracle 10g 最大8T,Oracle 11g 最大是128T。具體取決於blocksize 的大小。

The built-in LOB data types BLOB, CLOB, and NCLOB (stored internally) and BFILE (stored externally) can store large and unstructured data such as text, image, video, and spatial data. The size of BLOB, CLOB, and NCLOB data can be up to (232-1 bytes) * (the value of the CHUNK parameter of LOB storage).

1、Oracle 支持4 種類型的LOB:

CLOB:字符LOB。這種類型用於存儲大量的文本信息,如XML 或者只是純文本。這個數據類型需要進行字符集轉換,也就是說,在獲取時,這個欄位中的字符會從資料庫的字符集轉換為客戶的字符集,而在修改時會從客戶的字符集轉換為資料庫的字符集。

NCLOB:這是另一種類型的字符LOB。存儲在這一列中的數據所採用的字符集是資料庫的國家字符集,而不是資料庫的默認字符集。

BLOB:二進位LOB。這種類型用於存儲大量的二進位信息,如字處理文檔,圖像和你能想像到的任何其他數據。它不會執行字符集轉換。應用向BLOB 中寫入什麼位和位元組,BLOB就會返回什麼為和位元組。

BFILE:二進位文件LOB。這與其說是一個資料庫存儲實體,不如說是一個指針。帶BFILE列的資料庫中存儲的只是作業系統中某個文件的一個指針。這個文件在資料庫之外維護,根本不是資料庫的一部分。BFILE 提供了文件內容的只讀訪問。

2、LOB數據類型分類

2.1、按存儲數據的類型分:

(1)字符類型:

CLOB:存儲大量 單位元組 字符數據。

NLOB:存儲定寬 多位元組 字符數據。

(2)二進位類型:

BLOB:存儲較大無結構的二進位數據。

(3)二進位文件類型:

BFILE:將二進位文件存儲在資料庫外部的作業系統文件中。存放文件路徑。

2.2、按存儲方式分:

(1)存儲在內部表空間(內部LOB):

CLOB,NLOB和BLOB

(2)指向外部作業系統文件(外部LOB):

BFILE


二、Lob的存儲

我們建立含有lob欄位的表時,oracle會自動為lob欄位建立兩個單獨的segment,一個用來存放數據,另一個用來存放索引,並且它們都會存儲在對應表指定的表空間中。

如上例所示,每個lob欄位都對應兩個segment,其中存放lob數據的以SYS_LOB開頭,存放索引以SYS_IL開頭。

LOB 按「塊」(chunk)或(piece)來存儲,每個片段都可以訪問。


三、Lob與其它類型的轉換

通過TO_CLOB可以將CHAR,NCHAR,VARCHAR2,NVARCHAR2,NCLOB類型轉換成CLOB;

通過TO_LOB可以將LONG RAW轉換成BLOB,LONG轉換成CLOB;

通過TO_NCLOB可以將CHAR,NCHAR,VARCHAR2,NVARCHAR2,CLOB轉換成NCLOB。


四、Oracle資料庫的SYS_LOB

看看你的表里是不是存在blog,clob等類型的欄位,當我們所建立的表中含有lob型的數據時,oracle會為每個lob欄位生成一個獨立的segment用來存放數據,同時也建立了獨立的index segment .oracle對它們是單獨管理的。

普通表只會新增一個或兩個段對象.類型為TABLE和INDEX,數據就存放在表段中.索引就放在索引段中。但是LOB列則額外新增了兩個段對象,類型為LOBSEGMENT和LOBINDEX,LOBINDEX用於指向LOB段,找出其中的某一部分,所以存儲在表中的LOB存儲的是一個地址,或者說是一個指針,實際上表中的lob列中存的是一個地址段.然後在lobindex找到所有的地址段.然後在lobSegment中把所有地址段的值都讀取了來。所以lobSegment就保存了LOG列的真正的數據,所以會非常大,並且獨立於原始表存在。

先看看這個對應的表的欄位是否有數據,如果有你就無法刪除這個sys_lob$的對象。想減少空間的占用就清理歷史數據,或者重新導出導入下。


五、相關概念

關於LOB,我們可以使用dbms_metadata來獲得它的完整的腳本:

SELECT DBMS_METADATA.GET_DDL( 'TABLE', 'LOB_TABLE' ) FROM DUAL

1、表空間

保存lob數據的表空間可以不同於保存表數據的表空間,為LOB數據單獨使用一個表空間有利於備份和恢復以及空間管理但是lobindex和lobsegment必須在同一個表空間中

2、IN ROW

ENABLE STORAGE IN ROW
DISABLE STORAGE IN ROW

控制LOB數據是否總與表分開存儲(存儲在lobsegment中),或是有時可以與表一同存儲,而不用單獨放在lobsegment中。

如果設置了ENABLE STORAGE IN ROW,而不是DISABLE STORAGE IN ROW,小LOB(最多4,000位元組)就會像VARCHAR2一樣存儲在表本身中。只有當LOB超過了4,000位元組時,才會「移出」到lobsegment中

默認行為是啟用行內存儲ENABLE STORAGE IN ROW,如果lob存儲的數據大小能在表本身中放下,建議採用內聯存儲

3、CHUNK

塊(chunk)是邏輯上連續的一組資料庫塊(block),這也是LOB的最小分配單元。,每個LOB實例(每個行外存儲的LOB值)會占用至少一個CHUNK。一個CHUNK有一個LOB值使用,每個chunk的大小應該儘可能與實際lob數據的大小相近,以減少浪費空間;

4、PCTVERSION

控制lob的讀一致性

PCTVERSION控制著用於實現LOB數據版本化的已分配LOB空間的百分比(這些資料庫塊由某個時間點的LOB所用,並處在lobsegment的HWM以下)。對於許多使用情況來說,默認設置12%就足夠了,因為在很多情況下,你只是要INSERT和獲取LOB(通常不會執行LOB的更新;LOB往往會插入一次,而獲取多次)。因此,不必為LOB版本化預留太多的空間(甚至可以沒有)。

如果你的應用確實經常修改LOB,假設很頻繁地讀LOB,與此同時另外某個會話正在修改這些LOB,12%可能就太小了。如果處理LOB時遇到一個ORA-22924錯誤,解決方案不是增加undo表空間的大小,也不是增加undo保留時間(UNDO_RETENTION),如果你在使用手動undo管理,那麼增加更多RBS空間也不能解決這個問題。而是應該使用以下命令:

ALTER TABLE tabname MODIFY LOB (lobname) ( PCTVERSION n)

增加lobsegment中為實現數據版本化所用的空間大小。

5、CACHE

控制lobsegment數據是否存儲在緩衝區緩存中。默認的NOCACHE指示,每個訪問都是從磁碟的一個直接讀

ALTER TABLE tabname MODIFY LOB (lobname) ( CACHE );
ALTER TABLE tabname MODIFY LOB (lobname) ( NOCACHE );

六、查看ORACLE的LOB(BLOB和CLOB)對象占用的大小

1、查看Oracle中表空間及表數據大小

Select Segment_Name, Sum(bytes) / 1024 / 1024
From User_Extents
where SEGMENT_NAME LIKE 'SYS_LOB%'
GROUP BY Segment_Name
order by Sum(bytes) / 1024 / 1024 desc;

從返回的結果看,有一個segment名為"SYS_LOB0000701017C00045$$"的對象占用了大量的空間,這種帶有SYS_LOB***即LOB(BLOB和CLOB)對象占用資料庫的空間名稱。

2、根據segment_name,就可以從 dba_lobs 表里查到是哪個表,哪個欄位

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


後面會分享更多devops和DBA方面的內容,感興趣的朋友可以關注下!

文章來源: https://twgreatdaily.com/zh-tw/4uMC12wBJleJMoPMq_C_.html