- 參考:MySQL中varchar與char區別 博主:叫我大頭
一、char 和 varchar 區別
1、定長和變成
-
char:定長,長度固定;varchar:變長,長度可變;
- 當插入的字符串長度小於定義長度時,則會以不同的方式來處理,如char(10),表示存儲的是10個字符,無論你插入的是多少,都是10個,如果少於10個,則用空格填滿。而varchar(10),小於10個的話,則插入多少個字符就存多少個。
-
當所插入的字符串超出它們的長度時,視情況來處理:
- 如果是嚴格模式,則會拒絕插入並提示錯誤信息;
- 如果是寬松模式,則會截取然后插入;
2、存儲容量不同
- char:最多能存放的字符個數 255,和編碼無關;
- varchar:最多能存放 65532 個字符;
- varchar 的最大有效長度由最大行大小和使用的字符集確定,整體最大長度是 65,532字節;
3、存儲效率不同
- char:存儲長度固定,存儲速度較快,存儲效率較高;
- varchar:存儲長度不固定,存儲速度較慢,存儲效率較低;
- 原因:varchar 進行存儲前需要先計算長度,再加上計算的到字符串長度信息,一般 1-2 個 byte,所以每次存儲都要有額外的計算,得到長度等工作;
二、varchar
1、varchar 怎么知道所存儲字符串的長度?
- 先計算長度后,再加上計算的到字符串長度信息,一般1-2個byte,所以每次存儲都要有額外的計算,得到長度等工作;
- 對於 varchar 字段來說,需要使用一個(如果字符串長度小於 255)或兩個字節(長度大於 255)來存儲字符串的長度,因為他需要有一個 prefix 來表示他具體 bytes 數是多少;(因為varchar是變長的,沒有這個長度值他不知道如何讀取數據)。
2、varchar(M),既然 varchar 是自適應存儲空間,能不能把 M 值盡量往大了設置?
- 答案是否定的;
- mysql 把表信息放到內存中(查詢第一次后,就緩存住了,linux 下很明顯,但windows下似乎沒有,不知道為啥),這時內存的申請是按照固定長度來的,如果 varchar 很大就會有問題,所以還是應該按需索取。;
3、MySQL 中 varchar 最大長度是多少?
- 這不是一個固定的數字,先簡要說明一下限制規則:
-
限制規則
- 字段的限制在字段定義的時候有以下規則:
- 存儲限制
- varchar 字段是將實際內容單獨存儲在聚簇索引之外,內容開頭用1到2個字節表示實際長度(長度超過255時需要2個字節),因此最大長度不能超過65535字符;
- 編碼長度限制
- 字符類型若為 gbk,每個字符最多占2個字節,最大長度不能超過32766;
- 字符類型若為 utf8,每個字符最多占3個字節,最大長度不能超過21845;
- 若定義的時候超過上述限制,則varchar字段會被強行轉為 text 類型,並產生warning;
- 行長度限制
- 導致實際應用中 varchar 長度限制的是一個行定義的長度;
- MySQL要求一個行的定義長度不能超過 65535bytes,若定義的表長度超過這個值,則提示:
- 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;
- 存儲限制
- 字段的限制在字段定義的時候有以下規則:
-
計算例子
- 舉兩個例說明一下實際長度的計算:
-
若一個表只有一個varchar 類型,如定義為:create table t4(c varchar(N)) charset=gbk;
-
則此處 N 的最大值為 (65535-1-2) / 2 = 32766 個字符;
- 減1的原因是實際行存儲從第二個字節開始;
- 減2的原因是varchar頭部的2個字節表示長度;
- 除2的原因是字符編碼是gbk;
-
- 若一個表定義為: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個字節;
- 減30*3的原因是char(30)占用90個字節,編碼是utf8;
- 如果被varchar超過上述的規則 2(編碼長度限制),被強轉成 text 類型,則每個字段占用定義長度為11字節,當然這已經不是 “varchar” 了;
- 則此處N的最大值為 (65535-1-2-4-30*3)/3=21812;
- create table t4(c int, c2 char(30), c3 varchar(21812)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
- 則此處N的最大值為 (65535-1-2-4-30*3)/3=21812;
-
- 舉兩個例說明一下實際長度的計算:
4、在 MySQ L中用來判斷是否需要進行對據列類型轉換的規則
- 在一個數據表里,如果每一個數據列的長度都是固定的,那么每一個數據行的長度也將是固定的;
- 只要數據表里有一個數據列的長度的可變的,那么各數據行的長度都是可變的;
- 如果某個數據表里的數據行的長度是可變的,那么,為了節約存儲空間,MySQL會把這個數據表里的固定長度類型的數據列轉換為相應的可變長度類型.
- 例外:長度小於 4 個字符的 char 數據列不會被轉換 varchar 類型;
-
另外
- char 一般存儲很短的信息、固定長度的信息、十分頻繁改變的 column;
三、tinary 和 vartinary 區別
-
BINARY 和 VARBINARY 類型類似於 CHAR 和 VARCHAR,不同的是它們包含二進制字節字符串;
- BINARY:定長,長度固定;
- 指定長度之后,不足最大長度的,將在它們右邊填充‘\0’補齊以達到指定長度。
- 例如:指定列數據類型為BINARY(3),當插入‘a’ 時,存儲的內容實際為“a\0\0”,當插入“ab”時,實際存儲的內容為“ab\0”,不管存儲的內容是否達到指定的長度,其存儲空間均為指定的值M。
- VARBlNARY:變長,長度可變;
- 指定好長度之后,其長度可以在 0 到最大值之間;
- 例如:指定列數據類型為VARBINARY(20),如果插入的值的長度只有10,則實際存儲空間為 10 加 l,即其實際占用的空間為字符串的實際長度加 l。
- BINARY:定長,長度固定;
-
其使用的語法格式如下:
- column_name BINARY(M)或者VARBINARY(M);
四、二進制字符串
- 二進制字符串:用於存儲二進制的大對象,二進制字符串類型有 BIT、BLOB、BINARY 和 VARBINARY;
- 二進制的大對象:非傳統數據,如圖像、音頻和視頻文件、程序可執行文件等;
- TEXT 列被視為非二進制字符串(字符字符串);
- 二進制的大對象:非傳統數據,如圖像、音頻和視頻文件、程序可執行文件等;
- 在實際操作中,一般不建議將二進制的大文件存儲在數據庫中,而是將大對象的物理位置存儲在數據中;
五、嚴格模式
- mysql5.6之后的版本默認都是嚴格模式;
- 查看數據庫配置中變量名包含 mode 的配置信息:
-
show varibles like "%mode%";

-
- set session:只在當前操作界面有效;
- set global:全局有效;
- 設置嚴格模式:set global sql_mode = 'STRICT_TRANS_TABLES';
- 設置寬松模式:set sql_mode='NO_ENGINE_SUBSTITUTION';
六、MySQL 中漢字的編碼方式
- 一般 mysql,用的是 utf-8,不過這個最好看一下;
- 字符集分單字節和多字節:
- Latin1:一個字符占一個字節,最多能存放 65532 個字符;
- GBK:一個字符占兩個字節, 最多能存 32766 個字符(varchar);
- UTF8:一個字符占三個字節, 最多能存 21844 個字符(varchar);
- 更改表的編碼:
-
alter table tb_name character set utf8;
-
- 數據列的編碼格式:
-
alter table tb_name change first_name first_name varchar(20) character set utf8 not null;
-


