CHAR與VARCHAR詳解

前言:?

炎陵網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)!從網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、成都響應(yīng)式網(wǎng)站建設(shè)公司等網(wǎng)站項(xiàng)目制作,到程序開發(fā),運(yùn)營(yíng)維護(hù)。創(chuàng)新互聯(lián)從2013年開始到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)。

前面寫過一篇介紹int類型的文章,一直想寫一篇介紹字符串字段類型的文章,一直拖著也沒思路要怎么下手。最近多關(guān)注了下這方面的文章,決定還是把拖了好久的文章了結(jié)了吧。本篇文章主要會(huì)介紹字符串類型char及varchar的用法及區(qū)別。

本文實(shí)驗(yàn)環(huán)境為MySQL 5.7.23版本,存儲(chǔ)引擎為Innodb,sql_mode采用嚴(yán)格模式,字符集是utf8。

▍1.CHAR類型介紹

我們平時(shí)使用char類型定義字段時(shí),往往會(huì)指定其長(zhǎng)度M,即char(M)。其實(shí)M指的是字符數(shù),即這個(gè)字段最多存儲(chǔ)多少個(gè)字符,M可不指定,默認(rèn)為1,范圍是[0,255],單個(gè)字母、數(shù)字、中文等都是占用一個(gè)字符。utf8字符集下一個(gè)中文字符占用3個(gè)字節(jié)。下面我們簡(jiǎn)單測(cè)試下:

# 假設(shè)以如下建表語句創(chuàng)建測(cè)試表
CREATE TABLE `char_tb1` (
  `col1` char DEFAULT NULL,
  `col2` char(5) DEFAULT NULL,
  `col3` char(10) DEFAULT NULL
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

# 進(jìn)入數(shù)據(jù)庫查詢建表語句如下 發(fā)現(xiàn)char(M) M可不指定,默認(rèn)為1
mysql> show create table char_tb1\G
*************************** 1. row ***************************
       Table: char_tb1
Create Table: CREATE TABLE `char_tb1` (
  `col1` char(1) DEFAULT NULL,
  `col2` char(5) DEFAULT NULL,
  `col3` char(10) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

# 插入數(shù)據(jù) 可以看出M表示保存的最大字符數(shù),字母、數(shù)字、中文等都是占用一個(gè)字符
mysql> insert into char_tb1 (col1) values ('a'),('1'),('王'),(']');
Query OK, 4 rows affected (0.01 sec)
mysql> insert into char_tb1 (col1) values ('aa'),('12');
ERROR 1406 (22001): Data too long for column 'col1' at row 1
mysql> select * from char_tb1;
+------+------+------+
| col1 | col2 | col3 |
+------+------+------+
| a    | NULL | NULL |
| 1    | NULL | NULL |
| 王   | NULL | NULL |
| ]    | NULL | NULL |
+------+------+------+
4 rows in set (0.00 sec)
mysql> insert into char_tb1 (col2) values ('abcd'),('王-123'),('^*123'),('12'),('一二三四五');
Query OK, 5 rows affected (0.01 sec)
mysql> insert into char_tb1 (col2) values ('abcdef');
ERROR 1406 (22001): Data too long for column 'col2' at row 1
mysql> select * from char_tb1;
+------+-----------------+------+
| col1 | col2            | col3 |
+------+-----------------+------+
| a    | NULL            | NULL |
| 1    | NULL            | NULL |
| 王   | NULL            | NULL |
| ]    | NULL            | NULL |
| NULL | abcd            | NULL |
| NULL | 王-123          | NULL |
| NULL | ^*123           | NULL |
| NULL | 12              | NULL |
| NULL | 一二三四五      | NULL |
+------+-----------------+------+
9 rows in set (0.00 sec)

# 下面測(cè)試發(fā)現(xiàn)M的范圍是[0,255] 
mysql> alter table char_tb1 add column col4 char(0);
Query OK, 0 rows affected (0.10 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table char_tb1 add column col5 char(255);
Query OK, 0 rows affected (0.11 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table char_tb1 add column col5 char(256);
ERROR 1074 (42000): Column length too big for column 'col5' (max = 255); use BLOB or TEXT instead
▍2.VARCHAR類型介紹

同樣的,varchar(M)中的的M表示保存的最大字符數(shù),單個(gè)字母、數(shù)字、中文等都是占用一個(gè)字符。varchar可存儲(chǔ)的長(zhǎng)度范圍為0-65535字節(jié),此外,varchar需要使用1或者2個(gè)額外字節(jié)記錄字符串的長(zhǎng)度:如果列的最大長(zhǎng)度小于或等于255字節(jié),則只使用1個(gè)字節(jié)表示,否則使用2個(gè)字節(jié)。對(duì)于Innodb引擎,utf8字符集來說,單個(gè)中文字符占用3個(gè)字節(jié),所以varchar(M)中的M最大不會(huì)超過21845,即M的范圍是[0,21845),并且M必須指定。另外MySQL規(guī)定:?jiǎn)蝹€(gè)字段長(zhǎng)度不大于65535字節(jié);單行最大限制為65535,這里不包括TEXT、BLOB字段。即單張表中的所有varchar字段定義的長(zhǎng)度之和不能大于65535,所以并不是所有varchar(M)字段中的M都可以取到21844,下面我們來驗(yàn)證下:

# 假設(shè)以如下建表語句創(chuàng)建測(cè)試表
CREATE TABLE `varchar_tb1` (
  `col1` varchar(0) DEFAULT NULL
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

# 查看建表語句 增加字段 發(fā)現(xiàn)M必須指定
mysql> show create table varchar_tb1\G
*************************** 1. row ***************************
       Table: varchar_tb1
Create Table: CREATE TABLE `varchar_tb1` (
  `col1` varchar(0) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> alter table varchar_tb1 add column col2 varchar;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1

# 下面測(cè)試證明M最大可取到21844
mysql> CREATE TABLE `varchar_tb2` (col1 varchar(21844));
Query OK, 0 rows affected (0.04 sec)

mysql> CREATE TABLE `varchar_tb3` (col1 varchar(218445));
ERROR 1074 (42000): Column length too big for column 'col1' (max = 21845); use BLOB or TEXT instead

# 下面測(cè)試證明單行最大限制為65535字節(jié)
mysql> CREATE TABLE `varchar_tb3` (col1 varchar(10));
Query OK, 0 rows affected (0.04 sec)

mysql> alter table varchar_tb3 add column col2 varchar(21844);
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
mysql> alter table varchar_tb3 add column col2 varchar(21834);
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
mysql> alter table varchar_tb3 add column col2 varchar(21833);
Query OK, 0 rows affected (0.09 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show create table varchar_tb3\G
*************************** 1. row ***************************
       Table: varchar_tb3
Create Table: CREATE TABLE `varchar_tb3` (
  `col1` varchar(10) DEFAULT NULL,
  `col2` varchar(21833) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
▍3.CHAR與VARCHAR比較

CHAR類型是定長(zhǎng)的,MySQL總是根據(jù)定義的字符串長(zhǎng)度分配足夠的空間。當(dāng)保存CHAR值時(shí),在它們的右邊填充空格以達(dá)到指定的長(zhǎng)度,當(dāng)檢索到CHAR值時(shí),尾部的空格被刪除掉。

VARCHAR類型用于存儲(chǔ)可變長(zhǎng)字符串,存儲(chǔ)時(shí),如果字符沒有達(dá)到定義的位數(shù),也不會(huì)在后面補(bǔ)空格。但是,由于行是變長(zhǎng)的,在UPDATE時(shí)可能使行變得比原來更長(zhǎng),這就導(dǎo)致需要做額外的工作。如果一個(gè)行占用的空間增長(zhǎng),并且在頁內(nèi)沒有更多的空間可以存儲(chǔ),在這種情況下InnoDB需要分裂頁來使行可以放進(jìn)頁內(nèi),這樣會(huì)增加碎片。

下面簡(jiǎn)單總結(jié)下CHAR與VARCHAR字段類型的適用場(chǎng)景:

CHAR適合存儲(chǔ)很短的字符串,或者所有值都接近同一個(gè)長(zhǎng)度。例如,CHAR非常適合存儲(chǔ)密碼的MD5值,因?yàn)檫@是一個(gè)定長(zhǎng)的值。對(duì)于經(jīng)常變更的數(shù)據(jù),CHAR也比VARCHAR更好,因?yàn)槎ㄩL(zhǎng)的CHAR類型不容易產(chǎn)生碎片。對(duì)于非常短的列,CHAR比VARCHAR在存儲(chǔ)空間上也更有效率。例如用CHAR(1)來存儲(chǔ)只有Y和N的值,如果采用單字節(jié)字符集只需要一個(gè)字節(jié),但是VARCHAR(1)卻需要兩個(gè)字節(jié),因?yàn)檫€有一個(gè)記錄長(zhǎng)度的額外字節(jié)。

下面這些情況下使用VARCHAR是合適的:字符串很長(zhǎng)或者所要存儲(chǔ)的字符串長(zhǎng)短不一,差別很大;字符串列的最大長(zhǎng)度比平均長(zhǎng)度大得多;列的更新很少,所以碎片不是問題。

額外說明下,我們?cè)诙x字段最大長(zhǎng)度時(shí)應(yīng)該按需分配,提前做好預(yù)估。特別是對(duì)于VARCHAR字段,有人認(rèn)為反正VARCHAR數(shù)據(jù)類型是根據(jù)實(shí)際的需要來分配長(zhǎng)度的,還不如給大一點(diǎn)呢。但事實(shí)不是這樣的,比如現(xiàn)在需要存儲(chǔ)一個(gè)地址信息,根據(jù)評(píng)估,只要使用100個(gè)字符就可以了,我們可以使用VARCHAR(100)或VARCHAR(200)來存儲(chǔ),雖然它們用來存儲(chǔ)90個(gè)字符的數(shù)據(jù),其存儲(chǔ)空間相同,但是對(duì)于內(nèi)存的消耗是不同的。更長(zhǎng)的列會(huì)消耗更多的內(nèi)存,因?yàn)镸ySQL通常會(huì)分配固定大小的內(nèi)存塊來保存內(nèi)部值,尤其是使用內(nèi)存臨時(shí)表進(jìn)行排列或者操作時(shí)會(huì)特別糟糕。所以我們?cè)诜峙銿ARCHAR數(shù)據(jù)類型時(shí)仍然不能夠太過于慷慨。還是要評(píng)估實(shí)際需要的長(zhǎng)度,然后選擇一個(gè)最長(zhǎng)的字段來設(shè)置字符長(zhǎng)度。如果為了考慮冗余,可以留10%左右的字符長(zhǎng)度。千萬不能認(rèn)為VARCHAR是根據(jù)實(shí)際長(zhǎng)度來分配存儲(chǔ)空間,而隨意的分配長(zhǎng)度,或者說干脆使用最大的字符長(zhǎng)度。

總結(jié):?

本文分別介紹了CHAR與VARCHAR字段類型的使用方法,并且給出了二者的對(duì)比以及適用場(chǎng)景。在實(shí)際生產(chǎn)情況,需要具體情況具體分析,合適的才是最好的,希望這篇文章能給到大家參考。

文章題目:CHAR與VARCHAR詳解
分享網(wǎng)址:http://bm7419.com/article48/gossep.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App設(shè)計(jì)、軟件開發(fā)、面包屑導(dǎo)航Google、營(yíng)銷型網(wǎng)站建設(shè)、自適應(yīng)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站網(wǎng)頁設(shè)計(jì)