概述
今天主要探討下Oracle數據庫底層存儲--字節序和字符集,下面一起來看看吧~
1、字節序
Oracle安裝在不同的服務器架構平臺,數據文件所采用的字節序也不相同。字節序有兩種,Big Endian和Little Endian。比如一般我們windows或者linux服務器用的CPU是Intel/AMD架構,那么數據文件保存格式為Little Endian,如果用的是IBM的Power PC,那么數據文件保存格式為Big Endian。
Big Endian和Little Endian具體在保存數據時有什么區別呢?我們舉例說明。
整數1920如果用4個字節(十六進制0X00000780)保存,那么在Big Endian的保存方法如下表所示。
我們再來看看Little Endian的保存方法。
根據上面的內容,我們可以知道在Little Endian下,保存整數1920是反向的
以下列出各個服務器平臺的ENDIAN格式。
2、字符集
計算機當初發明時大多用來處理數字,后來慢慢的用來處理文字。問題來了,計算機可不認識全世界這么多文字,甚至連26個英文字母也不認識。于是美國國家標準協會ANSI開始制作標準,比如用65表示字母A,用66來表示字母B,包括26個大小寫字母,數字和一些符號(100多個),這就是最初的ASCII碼。當初ASCII碼沒有超過128個,只用了7位來表示,最高位留給用作奇偶校驗。后來又被歐洲擴展到了8位,可以用來表示256個字符。
ASCII碼并沒有包括中文,要讓計算機認識中文,中國的標準化機構也開始制作了一些標準(GBK)。中國的漢字太多了,用一個字節可裝不下這么多(8個二進制位最多表示256個字符),于是采用了2個字節(理論上可以表示65536個字符),其他國家和地區也沒有閑著,比如日本的Shift_JIS編碼,香港臺灣的BIG5編碼,于是全世界產生了各種各種的字符編碼。
這樣問題又來了,而且是大問題。大家都各搞各的,這么多編碼,自己本地傳輸信息當然沒有問題。但是當一個中國人發GBK編碼的中文郵件給日本人,日本人的電腦如果只認識Shift_JIS編碼,那么計算機將會把所有GBK編碼按照Shift_JIS編碼來解釋,于是日本人看到的是所謂的“亂碼”。之所以叫所謂,因為計算機自認為它并沒有做錯,那些“亂碼”也是對應的字符,只是不常用,日本人看不懂而已,計算機懂的。
于是地球上的標準化組織領導們又開會討論了,還提出了一個偉大的想法,這就是UNICODE字符集。這種字符集的想法是用一套字符集把地球上所有的文字都包括進來。當然2個字節可裝不下全世界的所有字符,采用了4個字節(理論上可以表示4294967296個字符)。用UNICODE字符集實現的編碼有UTF32/UTF16/UTF8。
上面扯了這么多,那么我們在新建數據庫的時候,需要選擇數據庫的數據庫字符集(CHARACTER SET)和國家字符集(NATIONAL CHARACTER SET)。比如我們選擇數據庫字符集為 ZHS16GBK,國家字符集為AL16UTF16。它表示這個數據庫里Char,Varchar2采用的是GBK的編碼,而Nchar,Nvarchar2,Nclob采用UTF16編碼。
好,下面我們來做一個試驗,看看這些字符集里到底保存了什么內容。
SQL> SELECT * FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER LIKE '%CHARACTERSET%'; SQL> CREATE TABLE TESTCHAR (COL1 VARCHAR2(100),COL2 NVARCHAR2(100)); SQL> INSERT INTO TESTCHAR VALUES('DBSEEKER+廣東省廣州市','DBSEEKER+廣東省廣州市'); SQL> SELECT DUMP(COL1,16),DUMP(COL2,16) FROM TESTCHAR;
在上面我們新建一張表,表有兩個字段,COL1的字段類型為VARCHAR2使用的是數據庫字符集(ZHS16GBK),COL2的字段類型為NVARCHAR2使用國家字符集(AL16UTF16)。往兩個字段插入了同樣的文本內容'DBSEEKER+廣東省廣州市'。
接下來,我們DUMP了字段保存的十六進制內容,觀察到字段COL1的長度為21個字節,而字段COL2的長度為30字節,為什么同樣的文本內容保存在VARCHAR2和NVARCHAR2里面,底層的存儲內容完全不同呢?
原因就在于COL1和COL2使用了不同的字符集,不同字符集對應相同文字編碼定義也是不一樣的。
COL1使用GBK編碼,各個字節對應的字符。
COL2使用UTF16編碼,各個字節對應的字符。
通過上面觀察,我們可以知道GBK編碼是變長的,英文字母用1個字節保存,漢字用2個字節來保存。而UTF16則都是用2個字節來保存。Oracle數據文件里保存的文本字段內容就是各種編碼表相對應的字符編碼。