char和varchar的區別


char

char是定長的,插入數據不足規定長度的,右邊補空格,當然查詢出來的數據也會有空格,插入數據超過規定長度,會返回錯誤[22001][1406] Data truncation: Data too long for column 'name' at row 1MySQL並不會自動截短字符串。因為char是定長的,所以查詢的效率比varchar高(后面會將為什么效率高),但在列容量不能充分利用的情況下會造成一定的空間浪費。

varchar

varchar是不定長的,varchar類型的列是不定長的,在5.0版本以后的最大長度是65535字節(2^16),但是這個長度只是“系統長度”,這並不意味着你真的可以完全利用65535字節來存儲數據,因為varchar是不定長的,所以需要前兩個字節標記字段的實際長度,結尾還要用一個字節表示結束,這可以用u盤來說明,買到一個256G的u盤,用工具查看u盤的實際容量時,會發現不足256G,因為系統也要占用一部分。

需要注意的是65535只是字節個數,而且是理論字節個數,在減去頭尾的"系統"占用字節后,只剩下65532可用字節。那么我們建表的時候,能不能直接寫varchar(65532)呢?當然是不可以的,因為4.0之后,varchar后面的小括號里就不再是字節長度了,而是字符長度。
字節和字符個數之間的換算關系是根據編碼決定的:

編碼 長度
utf8 65532/3=21844(漢字占3個字符)
utf8mb4 65532/4=16383(漢字占4個字符,包含了生僻漢字和文字表情)

我們只列出了常用的編碼格式。

那么這是否意味着,在utf8mb4編碼下我們可以用varchar(16383)來定義一個列呢?

答案是要看情況,MySQL規定了一個row所有的字段加起來總長度不能超過65535字節,所以如果一個表只有一個列,那完全可以用varchar(16383)來定義這個列,如果這個表還有其他列,無論其他列多么短,都是會占用字節數的,所以,使用varchar(16383)來定義的時候,MySQL會返回錯誤提示:ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs,意思是row的容量太大,超出了row的最大容量65535,如果不改變列的長度的話,推薦使用TEXT or BLOBs類型。

所以,如果我們要創建一個只包含兩個字段的表(編碼是utf8mb4),一列是主鍵,一列是字符串,字符串的最大長度是多少呢?你可以先自己算一下,再往下看。

長度
id int(11)
article varchar((65535-4)/4=16382)

為什么65535要減去4呢?因為int(11)占4個字節,那么在utf8編碼情況下,還是同樣的數據結構,article的最大長度有事多少呢?

長度
id int(11)
article varchar((65535-4)/3=21843)

相信這次你一定算對了。

為什么char類型查詢效率高

這是由他們在磁盤上存放的不同形式決定的,我們先來看一個圖:

 
char和varchar類型數據存儲示意圖.jpg

我們可以看到char類型在存放數據的時候,中間是沒有間隔的,數據本身是有空格的,但是數據段之間沒有間隔,因為我們在創建列的時候已經告訴 MySQL列的長度了, MySQL在查詢數據的時候,只需要按部就班尋找就行了,不需要在中途計算這個數據段的長度。

 

但是varchar類型的存放就不同了,在每個數據段開頭,都要有一段空間(1~2個字節)存放數據段的長度,在數據段的結尾還有一段空間(1個字節)標記此字段的節數。MySQL在讀取一個數據段的時候,首先要讀開頭,比如讀到了3,說明數據段的長度是3,之后就不多不少,只讀3個字節。所以MySQL在遍歷數據的時候,磁針要比char類型的列多讀很多次磁盤來獲取字段的真實長度,這就是為什么varchar比char查詢效率低的原因了。

應用

我們可以用varchar存放不定長的數據,比如人的名字,或者一篇博客的文章。可以用char存放定長的數據,比如身份證號和手機號,我們把一個列定義為mobile char(11),中國大陸的手機號最長,達到11位,香港是8位,瑞士是10位,所以定義成11位完全夠用,可以存放各國的手機號了。

附加

除了char和varchar類型,最常用的就是數值類型了,為了方便建表的時候計算列的最大長度,把數值類型占用的字節和值的范圍放在這里:


 

 

 

MySQL數值類型的取值范圍和占用字節數.png


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM