MySQL字符之char、varchar類型簡析
前言
我們都知道,MySQL中關(guān)于字符,有char和varchar兩種常用的類型,可能在平時的使用過程中,大家不會去關(guān)心這兩種類型的區(qū)別,只是會用就可以了,或者說看到過一些它們的區(qū)別,但是沒有時間去測試,今天有時間了,我將這兩種類型的具體情況實驗一把,讓大家直觀感受下,純屬分享,大神請繞道。
? 先說說理論吧。
? char類型為固定長度的字符串,比如說char(10),它定義了指定的字符串長度最大為10個字符,如果你現(xiàn)在輸入一個字符串為’12345678’,那么它在char類型中到底會占用多少個字符呢?答案是10個,后面缺少的2個字符,MySQL會自動補充為空值,然后進行存放。在取這個記錄的時候,char類型的會使用trim()函數(shù)去掉多余的空格,所以我們看到的還是8個字符的記錄。當輸入的字符長度大于最大的長度時,MySQL會自動報錯。
? varchar類型是長度可變的字符串,varchar(M)表示最大長度是M個字符,varchar的最大實際長度由最大的行的大小和使用的字符集確定。例如varchar(50)定義了一個最大長度為50的字符串,如果插入的字符串只有20個字符,那么實際存儲的字符串具有21個字符,因為varchar會自動包含一個字符串結(jié)束字符。varchar在值保存和檢索時,尾部的空格仍然保留。
? 介紹完概念,我們來看具體的實踐過程,本文中使用的測試版本為MySQL5.7.22版本。
1.測試char的trim()功能
? 首先創(chuàng)建一個表,這個表里面包含兩個字段,d_char和d_varchar,設(shè)定初始的字符長度都為4,如下:
查看一下,
此時,我們插入兩條記錄,每條記錄都是’ab ',注意,ab后面有2個空格,
然后我們使用mysql里面的concat函數(shù)進行字符連接,給每條記錄的左右分別添加小括號,
此時我們可以看到,d_char的ab后面的空格被取消掉了,而d_varchar后面的空格還依舊存在。
2.測試兩種字符類型的最大長度
首先看看char的最大長度,我們設(shè)置的值為256,結(jié)果如下
所以,char類型的長度取值范圍為0~255個字符
上面提到了varchar的最大實際長度由最大的行的大小和使用的字符集確定,這里我們進行實驗:
可以看到,字符集不一樣,最后的max的值也是不一樣的,
utf8模式下是0~21845,一個字符占三個字節(jié),最多能存 21844 個字符
latin1模式下是0~65535,一個字符占一個字節(jié),最多能存放 65532 個字符
gbk模式下是0~32767,一個字符占兩個字節(jié),最多能存 32766 個字符
若定義的時候超過上述限制,則varchar字段會被強行轉(zhuǎn)為text類型,并產(chǎn)生warning。
可能這里有人要問了,為什么最大值是32767,而最多只能放32766個字符呢?
舉兩個例說明一下實際長度的計算。
a) 若一個表只有一個varchar類型,如定義為
create table t4(c varchar(N)) charset=gbk;
則此處N的最大值為(65535-1-2)/2= 32766 個字符。
減1的原因是實際行存儲從第二個字節(jié)開始’;
減2的原因是varchar頭部的2個字節(jié)表示長度;
除2的原因是字符編碼是gbk。
b) 若一個表定義為
create table t4(c int, c2 char(30), c3 varchar(N)) charset=utf8;
則此處N的最大值為 (65535-1-2-4-30*3)/3=21812
減1和減2與上例相同;
減4的原因是int類型的c占4個字節(jié);
減30*3的原因是char(30)占用90個字節(jié),編碼是utf8。
如果被varchar超過上述的b規(guī)則,被強轉(zhuǎn)成text類型,則每個字段占用定義長度為11字節(jié),當然這已經(jīng)不是“varchar”了。
則此處N的最大值為 (65535-1-2-4-30*3)/3=21812
3.MySQL的字段長度模式
? 字段長度的模式分為嚴格模式和不嚴格模式,在嚴格模式下,如果我們想給一個字段中插入一個大于規(guī)定長度的字符串,MySQL會給出錯誤提示,例如我們的表:
? 當我們插入一個大于4字符的記錄時,
? 如果在非嚴格模式下,mysql會自動截斷超出最大長度的字符,
? 上面的操作是,我們先把字段模式改為非嚴格模式,然后查詢更改,確保更改生效,接著我們插入’abcde’字符串,發(fā)現(xiàn)它可以被成功執(zhí)行,但是包含兩個警告,查看警告可以發(fā)現(xiàn),一些數(shù)據(jù)被截斷了,
實驗部分的內(nèi)容基本就完成了,這里我們進行幾點分析:
1.MySQL為什么要設(shè)置這兩種類型?它們各自有什么優(yōu)點?
? char是固定長度的,它的存取速度比varchar快,方便程序的存儲于查找,但是它需要浪費一定的空間,可以看做是一種以空間換時間的方法。
? 而varchar的特點是可變長,當定義一個varchar(10)而只存入了4個字符,此時varchar會直接將字符記錄的長度變?yōu)?,從而節(jié)省空間,它可以看做是一種用時間換取空間的方法。
? char的存儲方式是,對英文字符(ASCII)占用1個字節(jié),對一個漢字占用兩個字節(jié);而varchar的存儲方式是,對每個英文字符占用2個字節(jié),漢字也占用2個字節(jié),兩者的存儲數(shù)據(jù)都非unicode的字符數(shù)據(jù)。
2.兩種類型適應(yīng)的情況分析。
關(guān)于char:
? CHAR適合存儲很短的字符串,或者所有值都接近同一個長度。
? 對于經(jīng)常變更的數(shù)據(jù),CHAR也比VARCHAR更好,因為定長的CHAR類型不容易產(chǎn)生碎片。
對于非常短的列,CHAR在存儲空間上也更有效率。例如用char(1)來存儲只有Y和N的值,只需要一個字節(jié),但是varchar卻需要兩個字節(jié),因為還一個記錄長度的額外字節(jié)。
關(guān)于varchar
? VARCHAR類型用于存儲可變長字符串,是最常見的字符串數(shù)據(jù)類型。它比定長類型 更節(jié)省空間,因為它僅使用必要的空間(例如,越短的字符串使用越少的空間)。
? VARCHAR節(jié)省了存儲空間,所以對性能也有幫助。但是,由于行是變長的,在UPDATE時可能使行變得比原來更長,這就導(dǎo)致需要做額外的工作。如果一個行占用 的空間增長,并且在頁內(nèi)沒有更多的空間可以存儲,在這種情況下,不同的存儲引擎的處理方式是不一樣的。例如,MyISAM會將行拆成不同的片段存儲,InnoDB 則需要分裂頁來使行可以放進頁內(nèi)。
? VARCHAR需要使用1或2個額外字節(jié)記錄字符串的長度:如果列的最大長度小于或等于255字節(jié),則只使用1個字節(jié)表示,否則使用2個字節(jié)。假設(shè)采用latinl字符集 ,一個varchar(10)的列需要11個字節(jié)的存儲空間。varchar(1000)的列則需要1002個字節(jié),因為需要2個字節(jié)存儲長度信息。
適用情況:
? 1、對于MyISAM表,盡量使用Char,對于那些經(jīng)常需要修改而容易形成碎片的myisam和isam數(shù)據(jù)表就更是如此,它的缺點就是占用磁盤空間;
? 2、對于InnoDB表,因為它的數(shù)據(jù)行內(nèi)部存儲格式對固定長度的數(shù)據(jù)行和可變長度的數(shù)據(jù)行不加區(qū)分(所有數(shù)據(jù)行共用一個表頭部分,這個標頭部分存放著指向各有關(guān)數(shù)據(jù)列的指針),所以使用char類型不見得會比使用varchar類型好。事實上,因為char類型通常要比varchar類型占用更多的空間,所以從減少空間占用量和減少磁盤i/o的角度,使用varchar類型反而更有利;
? 3、存儲很短的信息,比如門牌號碼101,201……這樣很短的信息應(yīng)該用char,因為varchar還要占個byte用于存儲信息長度,本來打算節(jié)約存儲的現(xiàn)在得不償失。
? 4、固定長度的。比如使用uuid作為主鍵,那用char應(yīng)該更合適。因為他固定長度,varchar動態(tài)根據(jù)長度的特性就消失了,而且還要占個長度信息。
? 5、十分頻繁改變的column。因為varchar每次存儲都要有額外的計算,得到長度等工作,如果一個非常頻繁改變的,那就要有很多的精力用于計算,而這些對于char來說是不需要的。
關(guān)于MySQL之char、varchar,你學廢了么?
總結(jié)
到此這篇關(guān)于MySQL字符之char、varchar類型簡析的文章就介紹到這了,更多相關(guān)MySQL之char、varchar類型內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mysql聚合統(tǒng)計數(shù)據(jù)查詢緩慢的優(yōu)化方法
這篇文章主要給大家介紹了關(guān)于mysql聚合統(tǒng)計數(shù)據(jù)查詢緩慢的優(yōu)化方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-02-02com.mysql.jdbc.Driver 和 com.mysql.cj.jdbc.Driver&n
大家在連接mysql的時候,啟動項目,會警告你推薦使用com.mysql.cj.jdbc.Driver?而不是com.mysql.jdbc.Driver,本文主要介紹了com.mysql.jdbc.Driver 和 com.mysql.cj.jdbc.Driver 的區(qū)別,具有一定的參考價值,感興趣的可以了解一下2024-03-03MySQL數(shù)據(jù)庫基本SQL語句教程之高級操作
對MySQL數(shù)據(jù)庫的查詢,除了基本的查詢外,有時候需要對查詢的結(jié)果集進行處理,下面這篇文章主要給大家介紹了關(guān)于MySQL數(shù)據(jù)庫基本SQL語句教程之高級操作的相關(guān)資料,需要的朋友可以參考下2022-06-06Mysql中TIMESTAMPDIFF函數(shù)的語法與練習案例
在應(yīng)用時經(jīng)常要使用這兩個函數(shù)TIMESTAMPDIFF和TIMESTAMPADD,下面這篇文章主要給大家介紹了關(guān)于Mysql中TIMESTAMPDIFF函數(shù)的語法與練習案例的相關(guān)資料,需要的朋友可以參考下2022-09-09linux(Centos7)下安裝mysql8.0.18的教程圖解
這篇文章主要介紹了linux(Centos7)安裝mysql8.0.18的教程,本文圖文并茂給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-11-11