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