【MySQL運維】實例講解MySQL中正確計算 Varchar 可存儲的最大長度


首先咱們要知道,存儲的最大長度沒一個固定的數值,根據不一樣的表結構設計有所不一樣,通常有如下幾個限制規則:

一、存儲限制
varchar 字段是將實際內容單獨存儲在聚簇索引以外,內容開頭用1到2個字節表示實際長度(長度超過255時須要2個字節),所以最大長度不能超過65535,官方是這麼說的:

Values in VARCHAR columns are variable-length strings. The length can be specified as a value from 0 to 255 before MySQL 5.0.3, and 0 to 65,535 in 5.0.3 and later versions.

In contrast to CHAR, VARCHAR values are stored as a one-byte or two-byte length prefix plus data. The length prefix indicates the number of bytes in the value.

A column uses one length byte if values require no more than 255 bytes, two length bytes if values may require more than 255 bytes.

二、編碼長度限制
字符類型若爲 gbk,則個字符最多佔2個字節,最大長度不能超過32766; 字符類型若爲utf8,則每一個字符最多佔3個字節,最大長度不能超過21845。 若定義的時候超過上述限制,則varchar字段會被強行轉爲text類型,併產生warning。

三、行長度限制
致使實際應用中varchar長度限制的是一個行定義的長度。 MySQL要求一個行的定義長度不能超過65535。若定義的表長度超過這個值,則提示 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。
這就是說,好比建立一個表,表結構中有兩個varhcar類型字段,那麼這兩個字段的總長度不能超過65535...

官方說明以下:
Every table has a maximum row size of 65,535 bytes.
This maximum applies to all storage engines, but a given engine might have additional constraints that result in a lower effective maximum row size.

四、控制位大小
MySQL 中的Varchar字符類型還保留了1個字節來留其它控制信息.

明白以上四個存儲規則之後,下面經過實例來講明!!!

實例一:若一張表中只有一個字段VARCHAR(N)類型,utf8編碼,則N最大值爲多少?
sql

如:create table tb_name1(a varchar(N)) default charset=utf8;app


則: N 最大值 =(65535-1-2)/3=21844
  • 減1的緣由是實際行存儲從第二個字節開始(這個必須減,你懂得.....不懂能夠去撞牆^o^....);
  • 減2的緣由是varchar頭部的2個字節表示長度;
  • 除3的緣由是字符編碼是utf8.

回到SQL下測試:
MariaDB [opdba]> create table tb_name1(a varchar(21844)) default charset=utf8;
Query OK, 0 rows affected (0.38 sec)

MariaDB [opdba]> drop table tb_name1;
Query OK, 0 rows affected (0.00 sec)

MariaDB [opdba]> create table tb_name1(a varchar(21845)) default charset=utf8;
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


實例二:若一張表中有一個字段VARCHAR(N)類型,而且有其它的字段類型,utf8編碼,則N的最大值爲多少?
運維

如:create table tb_name2(a int, b char(20), c varchar(N)) default charset=utf8;ide


則: N 最大值=(65535-1-2-4-20*3)/3=21822
  • 減1的緣由是實際行存儲從第二個字節開始;
  • 減2的緣由是varchar頭部的2個字節表示長度;  
  • 減4的緣由是a字段的int類型佔4個字節;
  • 減20*3的緣由是char(20)佔用60個字節,編碼是utf8。

回到sql下測試下:
MariaDB [opdba]> create table tb_name2(a int, b char(20), c varchar(21822)) default charset=utf8;
Query OK, 0 rows affected (0.28 sec)

MariaDB [opdba]> drop table tb_name2;
Query OK, 0 rows affected (0.20 sec)

MariaDB [opdba]> create table tb_name2(a int, b char(20), c varchar(21823)) default charset=utf8;
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(N)類型,而且有其它的字段類型,gbk編碼,則N的最大值爲多少?
測試

如:create table tb_name3(a int, b char(20), c varchar(50), d varchar(N)) default charset=gbk;ui


則:N最大值=(65535-1-1-2-4-20*2-50*2)/2=32693
  • 第一個減1的緣由是實際行存儲從第二個字節開始;
  • 第二個減1表示第二個varchar(50)頭部一個1個字節表示長度(小於255);
  • 減2的緣由是varchar頭部的2個字節表示長度;
  • 減20*2的緣由是char(20)佔用40個字節,編碼是gbk;
  • 減50*2的緣由是varchar(50)佔用100個字節,編碼是gbk;

回到SQL測試:
MariaDB [opdba]> create table tb_name3(a int, b char(20), c varchar(50), d varchar(32694)) default charset=gbk;

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編碼


MariaDB [opdba]> create table tb_name3(a int, b char(20), c varchar(50), d varchar(32693)) default charset=gbk;
spa

Query OK, 0 rows affected (0.18 sec)


因此在開發者或運維DBA設計表的時候要注意這個問題~~~,若是仍是不明白的就是你的腦袋有問題~!~呵呵~~~~~...歡迎來電交流!


本系列文章同步到:http://www.opdba.com/?p=303
設計

相關文章
相關標籤/搜索