淺析MySQL里char、varchar、text的區別及應用場景


一、char、varchar、text的應用場景

  在存儲字符串時, 可以使用char、varchar或者text類型, 那么具體使用場景呢?

1、char長度固定, 即每條數據占用等長字節空間;適合用在身份證號碼、手機號碼等定。

2、varchar可變長度,可以設置最大長度;適合用在長度可變的屬性。

3、text不設置長度, 當不知道屬性的最大長度時,適合用text。

  按照查詢速度: char最快, varchar次之,text最慢。

1、char:char(n)中的n表示字符數,最大長度是255個字符; 如果是utf8編碼方式, 那么char類型占255 * 3個字節。(utf8下一個字符占用1至3個字節)

2、varchar:varchar(n)中的n表示字符數,最大空間是65535個字節, 存放字符數量跟字符集有關系;

  MySQL5.0.3以前版本varchar(n)中的n表示字節數;MySQL5.0.3以后版本varchar(n)中的n表示字符數;

  varchar實際范圍是65532或65533, 因為內容頭部會占用1或2個字節保存該字符串的長度;如果字段default null(即默認值為空),整條記錄還需要1個字節保存默認值null。

       如果是utf8編碼, 那么varchar最多存65532/3 = 21844個字符。

3、text:跟varchar基本相同, 理論上最多保存65535個字符, 實際上text占用內存空間最大也是65535個字節; 考慮到字符編碼方式, 一個字符占用多個字節, text並不能存放那么多字符; 跟varchar的區別是text需要2個字節空間記錄字段的總字節數。

   由於varchar查詢速度更快, 能用varchar的時候就不用text。

二、char、varchar、text的具體區別

  最近有表結構設計中出現了varchar(10000)的設計引起了大家的討論,我們下面就來分析分析。

1、首先普及一下常識:

(1)char(n)和varchar(n)括號中n代表字符的個數,並不代表字節個數,所以當使用了中文的時候(UTF8)意味着可以插入m個中文,但是實際會占用m*3個字節。

(2)同時char和varchar最大的區別就在於char不管實際value都會占用n個字符的空間,而varchar只會占用實際字符應該占用的空間+1,並且實際空間+1<=n。

(3)超過char和varchar的n設置后,字符串會被截斷。

(4)char的上限為255字節,varchar的上限65535字節,text的上限為65535。

(5)char在存儲的時候會截斷尾部的空格,varchar和text不會。

(6)varchar會使用1-3個字節來存儲長度,text不會。

Value

CHAR(4)

Storage Required

VARCHAR(4)

Storage Required

''

'    '

4 bytes

''

1 byte

'ab'

'ab  '

4 bytes

'ab'

3 bytes

'abcd'

'abcd'

4 bytes

'abcd'

5 bytes

'abcdefgh'

'abcd'

4 bytes

'abcd'

5 bytes

   總體來說:

  1、char,存定長,速度快,存在空間浪費的可能,會處理尾部空格,上限255。

  2、varchar,存變長,速度慢,不存在空間浪費,不處理尾部空格,上限65535,但是有存儲長度實際65532最大可用。

  3、text,存變長大數據,速度慢,不存在空間浪費,不處理尾部空格,上限65535,會用額外空間存放數據長度,顧可以全部使用65535。

2、應用場景的問題:

  當 varchar(n) 后面的 n 非常大的時候,我們是使用 varchar 好,還是 text 好呢?

  這是個明顯的量變引發質變的問題。我們從2個方面考慮,第一是空間,第二是性能。

(1)首先從空間方面

從官方文檔中我們可以得知當varchar大於某些數值的時候,其會自動轉換為text,大概規則如下:

  • 大於varchar(255)變為 tinytext
  • 大於varchar(500)變為 text
  • 大於varchar(20000)變為 mediumtext

  所以對於過大的內容使用varchar和text沒有太多區別。

(2)從性能方面

  索引會是影響性能的最關鍵因素,而對於text來說,只能添加前綴索引,並且前綴索引最大只能達到1000字節。

  而貌似varhcar可以添加全部索引,但是經過測試,其實也不是。由於會進行內部的轉換,所以long varchar其實也只能添加1000字節的索引,如果超長了會自動截斷。

localhost.test>create table test (a varchar(1500)); Query OK, 0 rows affected (0.01 sec) localhost.test>alter table test add index idx_a(a); Query OK, 0 rows affected, 2 warnings (0.00 sec) Records: 0  Duplicates: 0  Warnings: 2 localhost.test>show warnings; +---------+------+---------------------------------------------------------+
| Level   | Code | Message                                                 |
+---------+------+---------------------------------------------------------+
| Warning | 1071 | Specified key was too long; max key length is 767 bytes |
| Warning | 1071 | Specified key was too long; max key length is 767 bytes |
+---------+------+---------------------------------------------------------+

從上面可以明顯單看到索引被截斷了。而這個767是怎么回事呢?這是由於innodb自身的問題,使用innodb_large_prefix設置。

從索引上看其實long varchar和text也沒有太多區別。

  所以我們認為當超過255的長度之后,使用varchar和text沒有本質區別,只需要考慮一下兩個類型的特性即可。(主要考慮text沒有默認值的問題)

CREATE TABLE `test` ( `id` int(11) DEFAULT NULL, `a` varchar(500) DEFAULT NULL, `b` text ) ENGINE=InnoDB DEFAULT CHARSET=utf8 +----------+------------+-----------------------------------+
| Query_ID | Duration   | Query                             |
+----------+------------+-----------------------------------+
|        1 | 0.01513200 | select a from test where id=10000 |
|        2 | 0.01384500 | select b from test where id=10000 |
|        3 | 0.01124300 | select a from test where id=15000 |
|        4 | 0.01971600 | select b from test where id=15000 |
+----------+------------+-----------------------------------+

  從上面的簡單測試看,基本上是沒有什么區別的,但是個人推薦使用varchar(10000),畢竟這個還有截斷,可以保證字段的最大值可控,如果使用text那么如果code有漏洞很有可能就寫入數據庫一個很大的內容,會造成風險

  故,本着short is better原則,還是使用varchar根據需求來限制最大上限最好。

三、各個字段類型的存儲需求

Data Type

Storage Required

TINYINT

1 byte

SMALLINT

2 bytes

MEDIUMINT

3 bytes

INT, INTEGER

4 bytes

BIGINT

8 bytes

FLOAT(p)

4 bytes if 0 <= p <= 24, 8 bytes if 25 <= p <= 53

FLOAT

4 bytes

DOUBLE [PRECISION], REAL

8 bytes

DECIMAL(M,D), NUMERIC(M,D)

Varies; see following discussion

BIT(M)

approximately (M+7)/8 bytes

 

 

 

 

 

 

 

 

 

 

Data Type

Storage Required Before MySQL 5.6.4

Storage Required as of MySQL 5.6.4

YEAR

1 byte

1 byte

DATE

3 bytes

3 bytes

TIME

3 bytes

3 bytes + fractional seconds storage

DATETIME

8 bytes

5 bytes + fractional seconds storage

TIMESTAMP

4 bytes

4 bytes + fractional seconds storage

 

 

 

 

 

 

 

 

 

 

Data Type

Storage Required

CHAR(M)

M × w bytes, 0 <= M <= 255, where w is the number of bytes required for the maximum-length character in the character set

BINARY(M)

M bytes, 0 <= M <= 255

VARCHAR(M), VARBINARY(M)

L + 1 bytes if column values require 0 – 255 bytes, L + 2 bytes if values may require more than 255 bytes

TINYBLOB, TINYTEXT

L + 1 bytes, where L < 28

BLOB, TEXT

L + 2 bytes, where L < 216

MEDIUMBLOB, MEDIUMTEXT

L + 3 bytes, where L < 224

LONGBLOB, LONGTEXT

L + 4 bytes, where L < 232

ENUM('value1','value2',...)

1 or 2 bytes, depending on the number of enumeration values (65,535 values maximum)

SET('value1','value2',...)

1, 2, 3, 4, or 8 bytes, depending on the number of set members (64 members maximum)


免責聲明!

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



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