您好,登錄后才能下訂單哦!
前述
VARCHAR和CHAR是兩種最主要的字符串類型。不幸的是,很難精確地解釋這些值是怎么存儲在磁盤和內(nèi)存中的,因為這跟存儲引擎的具體實現(xiàn)有關(guān)。下面的描述假設(shè)使用的存儲引擎是InnoDB和/或者MyISAM。如果使用的不是這兩種存儲引擎,請參考所使用的存儲引擎的文檔。
先看看VARCHAR和CHAR值通常在磁盤上怎么存儲。請注意,存儲引擎存儲CHAR或者VARCHAR值的方式在內(nèi)存中和在磁盤上可能不一樣,所以MySQL服務(wù)器從存儲引擎讀出的值可能需要轉(zhuǎn)換為另一種存儲格式。
VARCHAR類型
VARCHAR類型用于存儲可變長字符串,是最常見的字符串?dāng)?shù)據(jù)類型。它比定長類型更節(jié)省空間,因為它僅使用必要的空間(例如,越短的字符串使用越少的空間)。有一種情況例外,如果MySQL表使用ROW_FORMAT=FIXED創(chuàng)建的話,每一行都會使用定長存儲,這會很浪費空間。
VARCHAR需要使用1或2個額外字節(jié)記錄字符串的長度:如果列的最大長度小于或等于255字節(jié),則只使用1個字節(jié)表示,否則使用2個字節(jié)。假設(shè)采用latin1字符集,一個VARCHAR(10)的列需要11個字節(jié)的存儲空間。VARCHAR(1000)的列則需要1002個字節(jié),因為需要2個字節(jié)存儲長度信息。
VARCHAR節(jié)省了存儲空間,所以對性能也有幫助。但是,由于行是變長的,在UPDATE時可能使行變得比原來更長,這就導(dǎo)致需要做額外的工作。如果一個行占用的空間增長,并且在頁內(nèi)沒有更多的空間可以存儲,在這種情況下,不同的存儲引擎的處理方式是不一樣的。例如,MyISAM會將行拆成不同的片段存儲,InnoDB則需要分裂頁來使行可以放進頁內(nèi)。其他一些存儲引擎也許從不在原數(shù)據(jù)位置更新數(shù)據(jù)。
VARCHAR適用情況
下面這些情況下適用VARCHAR是合適的:
字符串列的最大長度比平均長度大很多
列的更新很少,所以碎片不是問題
使用了像UTF-8這樣復(fù)雜的字符集,每個字符都使用不同的字節(jié)數(shù)進行存儲
CHAR類型
CHAR類型是定長的:MySQL總是根據(jù)定義的字符串長度分配足夠的空間。當(dāng)存儲CHAR值時,MySQL會刪除所有的末尾空格。CHAR值會根據(jù)需要采用空格進行填充以方便比較。
CHAR適合存儲很短的字符串,或者所有值都接近同一個長度。例如,CHAR非常適合存儲密碼的MD5值,因為這是一個定長的值。對于經(jīng)常變更的數(shù)據(jù),CHAR也比VARCHAR更好,因為定長的CHAR類型不容易產(chǎn)生碎片。對于非常短的列,CHAR比VARCHAR在存儲空間上也更有效率。例如用CHAR(1)來存儲只有Y和N的值,如果采用單字節(jié)字符集只需要一個字節(jié),但是VARCHAR(1)卻需要兩個字節(jié),因為還有一個記錄長度的額外字節(jié)。
測試
下面通過例子來具體說明CHAR與VARCHAR行為上的不同,首先,我們創(chuàng)建一張只有一個CHAR(10)字段的表,并且往里面插入一些值:
CREATE TABLE char_test ( char_col CHAR(10) ); INSERT INTO char_test VALUES ('string1'). (' string2'). ('string3 ');
當(dāng)我們檢索這些值的時候,會發(fā)現(xiàn)string3末尾的空格被截斷了。
SELECT CONCAT("'", char_col, "'") FROM char_test;
執(zhí)行結(jié)果:
如果用VARCHAR(10)字段存儲相同的值,可以得到如下結(jié)果:
CREATE TABLE varchar_test ( varchar_col VARCHAR(10) ); INSERT INTO varchar_test VALUES ('string1'). (' string2'). ('string3 '); SELECT CONCAT("'", varchar_col, "'") FROM varchar_test;
執(zhí)行結(jié)果
VARCHAR(5)與VARCHAR(200)的區(qū)別
我們倘若用VARCHAR(5)和VARCHAR(200)來存儲'hello',我們知道這兩者的空間開銷是一樣的。那么我們可以讓VARCHAR的長度始終保持很大嗎?使用更短的列有什么優(yōu)勢嗎?
事實證明有很大的優(yōu)勢。更長的列會消耗更多的內(nèi)存,因為MySQL通常會分配固定大小的內(nèi)存塊來保存內(nèi)部值。尤其是使用內(nèi)存臨時表進行排序或操作時會特別糟糕。在利用磁盤臨時表進行排序時也同樣糟糕。
所以最好的策略是只分配真正需要的空間。
總結(jié)
當(dāng)我們?yōu)樽址愋偷淖侄芜x取類型的時候,判斷該選取VARCHAR還是CHAR,我們可以從以下幾個方面來考慮:
該字段數(shù)據(jù)集的平均長度與最大長度是否相差很小,若相差很小優(yōu)先考慮CHAR類型,反之,考慮VARCHAR類型。
若字段存儲的是MD5后的哈希值,或一些定長的值,優(yōu)先選取CHAR類型。
若字段經(jīng)常需要更新,則優(yōu)先考慮CHAR類型,由于CHAR類型為定長,因此不容易產(chǎn)生碎片。
對于字段值存儲很小的信息,如性別等,優(yōu)先選取CHAR類型,因為VARCHAR類型會占用額外的字節(jié)保存字符串長度信息。
總之一句話,當(dāng)我們能夠選取CHAR類型的時候,或者說空間消耗相對并不是影響因素的重點時,盡量選取CHAR類型,因為在其他方面,CHAR類型都有著或多或少的優(yōu)勢。而當(dāng)空間消耗成為了很大的影響因素以后,我們則考慮使用VARCHAR類型。
以上就是MySQL中CHAR和VARCHAR的區(qū)別的詳細內(nèi)容,更多請關(guān)注億速云其它相關(guān)文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。