企業(yè)做網(wǎng)站的流程深圳網(wǎng)絡營銷推廣渠道
作者簡介:嚴軍(花名吉遠),十年以上專注于數(shù)據(jù)庫存儲領域,精通Oracle、Mysql、OceanBase,對大數(shù)據(jù)、分布式、高并發(fā)、高性能、高可用有豐富的經(jīng)驗。主導過螞蟻集團核心系統(tǒng)數(shù)據(jù)庫升級,數(shù)據(jù)庫LDC單元化多活項目,常年負責螞蟻重大數(shù)據(jù)庫活動(如雙11、雙12、春節(jié)紅包大促),現(xiàn)任阿里云數(shù)據(jù)庫架構師和云計算專家,專注于金融行業(yè)數(shù)據(jù)庫架構設計和咨詢工作。
因最近筆者在協(xié)助金融客戶完成系統(tǒng)的平滑遷移與升級工作。隨著遷移系統(tǒng)數(shù)量的不斷增加,發(fā)現(xiàn)客戶對Oracle的使用的復雜度和深度都相當高。因此,本文列舉了Oracle的索引組織表、大對象的特性,以及遷移到OceanBase(簡稱OB)的相應方案,以供參考。希望能對大家有所幫助。
1、索引組織表(Index-Organized Table, IOT)
1.1 索引組織表介紹
? ?索引組織表是一類特殊的表,它將索引和表的數(shù)據(jù)存儲在一起(或者說實際上將所有數(shù)據(jù)都放入了索引中)。普通表的數(shù)據(jù)以無序(Heap)的方式存放在數(shù)據(jù)庫中。而索引組織表按照主鍵進行排序,以二叉樹的形式對表的數(shù)據(jù)進行存儲。
●索引組織表不存儲ROWID,它通過主鍵來訪問數(shù)據(jù)。
●索引組織表適合通過主鍵對數(shù)據(jù)進行訪問的應用。
優(yōu)點
1.快速的隨機訪問。索引和表的數(shù)據(jù)存儲在一起,如果對表進行更新,Oracle只更新索引結構。
2.快速的范圍掃描。索引組織表已經(jīng)按照主鍵對數(shù)據(jù)進行排序,因此,范圍掃描的速度是很快的。
3.更少的存儲需求。索引數(shù)據(jù)和表的數(shù)據(jù)存儲在一起,可以減少存儲需求。普通的索引條目只包含索引值和指向數(shù)據(jù)行的ROWID
組成
1.索引部分。存放主鍵值,頻繁訪問的部分非主鍵值,指向溢出區(qū)的ROWID
2.溢出部分。用于存放非主鍵值。溢出區(qū)存放在一個溢出表空間中。用戶可以指定溢出表空間。
1.2 問題業(yè)務場景
客戶反饋OMS遷移時部分SYS_IOT開頭的表遷移出現(xiàn)報錯,原來以為是系統(tǒng)表,但核對時發(fā)現(xiàn)通過 user_objects查詢能查到這個表。
最后確定這類表其實都是索引組織表的子表,且子表不支持任何操作。復現(xiàn)腳本如下:
-- 創(chuàng)建IOT時,必須要設定主鍵,否則報錯。
CREATE TABLE TEST_IOT
(id NUMBER PRIMARY KEY,
C1 VARCHAR2(50),
C2 VARCHAR2(10))
ORGANIZATION INDEX PCTTHRESHOLD 10 OVERFLOW;select object_name,object_type from user_objects where object_name like '%IOT%';
/*
SYS_IOT_OVER_96983 TABLE
SYS_IOT_TOP_96983 INDEX
TEST_IOT TABLE
*/-- 只需要對父表進行賦權和獲取DDL操作,子表不支持任何操作。
grant select on SYS_IOT_OVER_96983 to scott;
-- ORA-25191: cannot reference overflow table of an index-organized table
select dbms_metadata.get_ddl('TABLE','SYS_IOT_OVER_96983','APPTEST') from dual;
/* ORA-31603: object "SYS_IOT_OVER_96983" of type TABLE not found in schema "APPTEST"
ORA-06512: at "SYS.DBMS_METADATA", line 6478
ORA-06512: at "SYS.DBMS_SYS_ERROR", line 105
ORA-06512: at "SYS.DBMS_METADATA", line 6465
ORA-06512: at "SYS.DBMS_METADATA", line 9202
ORA-06512: at line 1
*/-- 查詢父子表對應關系
select TABLE_NAME,IOT_NAME from dba_tables where owner='APPTEST';
TEST_IOT
SYS_IOT_OVER_96983 TEST_IOT
1.3 遷移方案
●表結構遷移:通過dbcat進行結構遷移,索引組織表會被轉換成普通表(后續(xù)OMS會支持);
●數(shù)據(jù)遷移:由于Logminer捕獲不到增量日志,這類表只能離線遷移。離線遷移方案建議:
? ?○主鍵單字段場景:OMS效率尚可,也可以使用dataX或者導出CSV文件后導入OB的方式;
? ?○主鍵多字段場景:不建議使用OMS,建議datax或者導出方式。
2. 大對象(LOB類型)
2.1 大對象介紹
Oracle
Oracle包含4種大對象類型BLOB、CLOB、NCLOB、BFILE,存儲長度都為4G。具體如下:
●CLOB:內(nèi)部字符大對象,存儲單字節(jié)和多字節(jié)字符數(shù)據(jù)。支持固定寬度和可變寬度的字符集,常用于大文本的存儲。
●NCLOB:國家語言字符集大對象,存儲UNICODE類型的數(shù)據(jù),支持固定寬度和可變寬度的字符集。
●BLOB:內(nèi)部二進制大對象,存儲非結構化的二進制數(shù)據(jù)大對象,它可以被認為是沒有字符集語義的比特流,一般是圖像、聲音、視頻等文件。
●BFILE:外部二進制文件,存儲在數(shù)據(jù)庫外的系統(tǒng)文件,只讀的,數(shù)據(jù)庫會將該文件當二進制文件處理。
OB
LOB 全稱為大對象數(shù)據(jù)類型(Large Object),包括 BLOB 和 CLOB,用來存儲大型和非結構化數(shù)據(jù),例如文本、圖像、視頻和空間數(shù)據(jù)等。本文主要提供 OceanBase 數(shù)據(jù)庫當前版本所支持的大對象數(shù)據(jù)類型的概覽和使用限制。
大對象數(shù)據(jù)類型概覽
OceanBase 數(shù)據(jù)庫當前版本所支持的大對象數(shù)據(jù)類型的信息如下表所示。
類型 | 長度 | 定義長度上限(字符) | 字符集 |
BLOB | 變長 | 48 MB | BINARY |
CLOB | 變長 | 48 MB | 與租戶的字符集一致 |
說明:與 Oracle 通過 LOB Locator 引用數(shù)據(jù)不同,在 OceanBase 數(shù)據(jù)庫中,LOB Locator 與數(shù)據(jù)保存在同一結構中。
2.2 遷移方案
●BLOB/CLOB:確定在OB支持的最大長度范圍內(nèi),平遷。超出最大范圍需要業(yè)務改造;
●NCLOB:OB不支持 nclob,OMS在遷移中會將字段類型轉成 nvarchar2 。注意nvarchar2 上限為 32767 個字節(jié);
●BFILE:建議在Oracle中使用代碼轉成BLOB后遷移,案例如下:
-- BFile實際上是Oracle數(shù)據(jù)庫指向操作系統(tǒng)文件的一個指針。
-- 讀取操作系統(tǒng)文件并轉為BLOB代碼:-- 創(chuàng)建測試文件
touch /home/oracle/test.jpg
-- 創(chuàng)建directory對象
create directory obtest as '/home/oracle/xxx';
grant read on directory obtest to <username>;
create table obfiletest(col1 bfile,cole2 blob);
INSERT INTO obfiletest(col1) VALUES (BFILENAME ('obtest', 'test.jpg'));-- BFILE轉BLOB
Declarev_bfile Bfile;v_blob Blob;v_dest Number := 1;v_lang Number := 1;
Beginv_bfile := bfilename('OBTEST', 'test.jpg');--dbms_output.put_line(v_bfile);dbms_lob.createtemporary(v_blob, True);dbms_lob.fileopen(v_bfile, dbms_lob.file_readonly);dbms_output.put_line(dbms_lob.getlength(v_bfile));dbms_lob.loadblobfromfile(dest_lob => v_blob, src_bfile => v_bfile,amount => dbms_lob.getlength(v_bfile),dest_offset => v_dest, src_offset => v_lang);Update obfiletest Set cole2 = v_blob;dbms_lob.fileclose(file_loc => v_bfile);
End;
/
2.3 關于CLOB字段的UNIQUE INDEX
●在創(chuàng)建CLOB字段的同時,Oracle會自動創(chuàng)建一個UNIQUE INDEX;OB支持CLOB字段類型,但不會自動創(chuàng)建UNIQUE INDEX(手工創(chuàng)建會報錯)
●方案:OB不支持該index,直遷數(shù)據(jù)即可(OMS遷移會忽略)。在做對象校驗時需要忽略這類index。
create table test001 (uinfo clob
);
insert into test001 values ('
{"employees":[{"firstName":"Bill","lastName":"Gates","creation_time":"2021-01-01","age":"30"},{"firstName":"George","lastName":"Bush","creation_time":"2021-06-01","age":"26"},{"firstName":"Thomas","lastName":"Carter","creation_time":"2020-03-01","age":"23"}]
}
');
commit;select * from dba_indexes where table_name='TEST001';SELECT INDEX_NAME,TABLE_NAME,TABLE_OWNER,DBMS_METADATA.get_ddl('INDEX',INDEX_NAME,'APPTEST') INDEX_DDLFROM user_indexes --當前用戶下的索引WHERE table_name = 'TEST001';-- 對應DDLCREATE UNIQUE INDEX "APPTEST"."SYS_IL0000101865C00001$$" ON "APPTEST"."TEST001" (PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)TABLESPACE "USERS" PARALLEL (DEGREE 0 INSTANCES 0)