一、關於UTF-8
UTF-8
Unicode Transformation Format-8bit。是用以解決國際上字符的一種多字節編碼。
它對英文使用8位(即一個字節) ,中文使用24位(三個字節)來編碼。
UTF-8
包含全世界所有國家需要用到的字符,是國際編碼,通用性強。
UTF-8
編碼的文字可以在各國支持UTF8字符集額的瀏覽器上顯示。
如果是UTF8
編碼,則在外國人的英文IE也能顯示中文,他們無需下載IE的中文語言支持包。
二、關於GBK
GBK
是國家標准GB2312基礎上擴容后兼容GB2312的標准。GBK
的文字編碼是用雙字節來表示的,即不論中、英文字符均使用雙字節來表示,為了區分中文,將其最高位都設定成1。GBK
包含全部中文字符,是國家編碼,通用性比UTF8差,不過UTF8占用的數據庫比GBK
大。
三、關於utf8mb4
MySQL 5.5 之前,UTF8 編碼只支持1-3個字節,只支持BMP這部分的unicode編碼區,BMP是從哪到哪?
戳這里 基本就是 0000 ~ FFFF 這一區。
從mysql 5.5 開始,可支持4個字節UTF編碼utf8mb4,一個字符最多能有4字節,所以能支持更多的字符集。
utf8mb4 is a superset of utf8
tf8mb4兼容utf8,且比utf8能表示更多的字符。
至於什么時候用,看你做的什么項目了。。。
在做移動應用時,會遇到iOS
用戶在文本的區域輸入emoji
表情,如果不做一定處理,就會導致插入數據庫異常。
四、漢字長度與編碼有關
MySql 5.0 以上的版本:
1、一個漢字占多少長度與編碼有關:
- UTF-8:一個漢字 = 3個字節,英文是一個字節
- GBK: 一個漢字 = 2個字節,英文是一個字節
2、varchar(n) 表示n個字符,無論漢字和英文,MySql
都能存入 n
個字符,僅實際字節長度有所區別。
3、MySQL檢查長度,可用SQL語言
SELECT LENGTH(fieldname) FROM tablename
五、實際測試
1、首先使用utf8
創建 str_test
表。
CREATE TABLE `str_test` (
`name_chn` varchar(20) NOT NULL,
`name_en` varchar(20) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=62974 DEFAULT CHARSET=utf8
然后插入值
mysql> insert into str_test values ('我愛Ruby', 'I Love Ruby!');
Query OK, 1 row affected (0.02 sec)
打開irb
>> "我愛Ruby".size
=> 6
>> "I Love Ruby!".size
=> 12
>>
從MySQL中查詢出來的結果,對比
mysql> select * from str_test;
+------------+--------------+
| name_chn | name_en |
+------------+--------------+
| 我愛Ruby | I Love Ruby! |
+------------+--------------+
1 row in set (0.02 sec)
mysql> select length(name_chn) from str_test;
+------------------+
| length(name_chn) |
+------------------+
| 10 |
+------------------+
1 row in set (0.01 sec)
3[一個漢字三字節] * 2 + 1[一個英文一字節] * 4 = 10
mysql> select length(name_en) from str_test;
+-----------------+
| length(name_en) |
+-----------------+
| 12 |
+-----------------+
1 row in set (0.00 sec)
10[一個英文一字節] * 1 + 2[空格一字節] * whitespace = 12
2、使用 GBK
做測試
創建表
CREATE TABLE `str_test` (
`name_chn` varchar(20) NOT NULL,
`name_en` varchar(20) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=62974 DEFAULT CHARSET=gbk
插入數據,並且測試
mysql> insert into str_test values ('我愛Ruby', 'I Love Ruby!');
Query OK, 1 row affected (0.00 sec)
mysql> select * from str_test;
+------------+--------------+
| name_chn | name_en |
+------------+--------------+
| 我愛Ruby | I Love Ruby! |
+------------+--------------+
1 row in set (0.01 sec)
GBK
中文是兩個字節,英文是一個字節。
mysql> select length(name_chn) from str_test;
+------------------+
| length(name_chn) |
+------------------+
| 8 |
+------------------+
1 row in set (0.00 sec)
2[中文兩個字節] * 2 + 4[英文一個字節] * 1 = 8
mysql> select length(name_en) from str_test;
+-----------------+
| length(name_en) |
+-----------------+
| 12 |
+-----------------+
1 row in set (0.00 sec)
10[英文一個字節] * 1 + 2[空格一個字節] * whitespace = 12
六、關於varchar 最多能存多少值
-
mysql的記錄行長度是有限制的,不是無限長的,這個長度是
64K
,即65535
個字節,對所有的表都是一樣的。 -
MySQL對於變長類型的字段會有1-2個字節來保存字符長度。
-
當字符數小於等於255時,MySQL只用1個字節來記錄,因為2的8次方減1只能存到255。
-
當字符數多余255時,就得用2個字節來存長度了。
-
在
utf-8
狀態下的varchar,最大只能到 (65535 - 2) / 3 = 21844 余 1。 -
在
gbk
狀態下的varchar, 最大只能到 (65535 - 2) / 2 = 32766 余 1
使用 utf-8
創建
mysql> CREATE TABLE `str_test` (
-> `id` tinyint(1) NOT NULL,
-> `name_chn` varchar(21845) NOT NULL
-> ) ENGINE=InnoDB AUTO_INCREMENT=62974 DEFAULT CHARSET=utf8
-> ;
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> CREATE TABLE `str_test` (
-> `id` tinyint(1) NOT NULL,
-> `name_chn` varchar(21844) NOT NULL
-> ) ENGINE=InnoDB AUTO_INCREMENT=62974 DEFAULT CHARSET=utf8
->
->
-> ;
Query OK, 0 rows affected (0.06 sec)
使用gbk
創建
當存儲長度為 32768 失敗~
mysql> CREATE TABLE `str_test` (
-> `id` tinyint(1) NOT NULL,
-> `name_chn` varchar(32768) NOT NULL
-> ) ENGINE=InnoDB AUTO_INCREMENT=62974 DEFAULT CHARSET=gbk
-> ;
ERROR 1074 (42000): Column length too big for column 'name_chn' (max = 32767); use BLOB or TEXT instead
當存儲長度為 32767 失敗~
mysql> CREATE TABLE `str_test` ( -> `id` tinyint(1) NOT NULL,
-> `name_chn` varchar(32767) NOT NULL
-> ) ENGINE=InnoDB AUTO_INCREMENT=62974 DEFAULT CHARSET=gbk
-> ;
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
當存儲長度為 32766 成功~
mysql> CREATE TABLE `str_test` (
-> `id` tinyint(1) NOT NULL,
-> `name_chn` varchar(32766) NOT NULL
-> ) ENGINE=InnoDB AUTO_INCREMENT=62974 DEFAULT CHARSET=gbk
-> ;
Query OK, 0 rows affected (0.03 sec)
smallint 用兩個字節存儲,所以
2[smallint] + 32766 * 2[varchar存儲長度] + 2[2個字節來存長度] > 65535
所以失敗~
mysql> CREATE TABLE `str_test` (
-> `id` smallint(1) NOT NULL,
-> `name_chn` varchar(32766) NOT NULL
-> ) ENGINE=InnoDB AUTO_INCREMENT=62974 DEFAULT CHARSET=gbk
-> ;
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
#####七、數值類型所占的字節
類型 | 所占字節 |
---|---|
int | 4 字節 |
smallint | 2 字節 |
tinyint | 1 字節 |
decimal | 變長 |
官方關於decimal
的描述如下
Values for DECIMAL (and NUMERIC) columns are represented using a binary format that packs nine decimal (base 10) digits into four bytes.
Storage for the integer and fractional parts of each value are determined separately.
Each multiple of nine digits requires four bytes, and the “leftover” digits require some fraction of four bytes.
The storage required for excess digits is given by the following table.
翻譯為中文
使用二進制格式將9個十進制(基於10)數壓縮為4個字節來表示DECIMAL列值。
每個值的整數和分數部分的存儲分別確定。
每個9位數的倍數需要4個字節,並且“剩余的”位需要4個字節的一部分。
下表給出了超出位數的存儲需求:
Leftover Digits | Number Of Bytes |
---|---|
0 | 0 |
1 | 1 |
2 | 1 |
3 | 2 |
4 | 2 |
5 | 3 |
6 | 3 |
7 | 4 |
8 | 4 |
那:decimal(10,2)占幾個字節?
1、首先 10 指的是整數與小數部分的總長度, 2指的是小數部分的長度。那么整數部分就只有 10 - 2 = 8 位
2、因為整數與小數的存儲市各自獨立確定的,所以他們各自所占用空間的綜合就是所占的總空間了。
3、對表可知,整數部分8位占了4個字節,小數部分2位占了1個字節,所以decimal(10,2)總共占了 4 + 1 = 5 個字節。
4、decimal(6,2) 整數部分(6 - 2 = 4) 位占2字節,小數部分2位占1字節,總共占3字節。
八、總結
varchar 字段是將實際內容單獨存儲在聚簇索引之外,內容開頭用1到2個字節表示實際長度(長度超過255時需要2個字節),因此最大長度不能超過65535。
- UTF-8:一個漢字 = 3個字節,英文是一個字節
- GBK: 一個漢字 = 2個字節,英文是一個字節
在utf-8
狀態下,漢字最多可以存 21844個字符串, 英文也為 21844個字符串。
在gbk
狀態下,漢字最多可以存 32766個字符串,英文也為 32766個字符串。