mysql的varchar與text對比

varchar和text是mysql字符存儲爭議比較多的領域,究竟大字段用那個比較好,我們來對比一下,然後自行選擇.


大小對比
VARCHAR:varchar在mysql中必須滿足最大行寬度限制,也就是 65535(16k)字節,而varchar本身是按字符串個數來定義的,在mysql中使用uft-8字符集一個字符佔用三個字節,所以單表varchar實際佔用最大長度如下.
    1.使用utf-8字符編碼集varchar最大長度是(65535-2)/3=21844個字符(超過255個字節會有2字節的額外佔用空間開銷,所以減2,如果是255以下,則減1)。
    2.使用 utf-8mb4字符集,mysql中使用 utf-8mb4 字符集一個字符佔用4個字節,所以 varchar 最大長度是(65535-2)/4=16383 個字符(超過255個字節會有2字節的額外佔用空間開銷,所以減2,如果是255以下,則減1)。


TEXT:最大限制是64k個字節,但是支持溢出存儲,雖然也受單表65535最大行寬度限制.但mysql中每個BLOB和TEXT列實際只佔其中的5至9個字節,其他部分將進行溢出存儲。所以實際佔用表最大行寬度爲9+2字節,外加的是額外開銷
    1.如果使用utf-8字符集,那麼單字段佔用最大長度也是21844個字符.
    2.不過單表可以設置多個text字段,這就突破了單表最大行寬度65535的限制


其他text:

text字段是分長中短類型,不像varchar只有一種,除了上面的text,還有下面三個.

TinyText:最大長度255個字節,實際上是個沒什麼意義的類型了.

MEDIUMTEXT:最大長度限制16M個字節。和普通text一樣也支持溢出存儲,所以實際佔用表最大行寬度爲9+3字節,外加的是額外開銷
LONGTEXT:最大長度限制4G個字節。和普通text一樣也支持溢出存儲,所以實際佔用表最大行寬度爲9+4字節,外加的是額外開銷

----------------------------------------

示例:

#VARCHAR單表單字段最長不能超過21844
CREATE TABLE test(
    va VARCHAR(21845)
)DEFAULT CHARSET=utf8;
[Err] 1118 - 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
#這樣就可以了
CREATE TABLE test(
    va VARCHAR(21844)
)DEFAULT CHARSET=utf8;
受影響的行: 0
時間: 0.155s
#雖然每個BLOB和TEXT列 賬戶只佔其中的5至9個字節。但是還不夠
CREATE TABLE test(
    va VARCHAR(21841),
    tx text
)DEFAULT CHARSET=utf8;
[Err] 1118 - 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
#然後9+2就可以了
CREATE TABLE test(
    va VARCHAR(21840),
    tx text
)DEFAULT CHARSET=utf8;
受影響的行: 0
時間: 0.170s


額外佔用空間開銷說明:
varchar 小於255byte  1byte overhead
varchar 大於255byte  2byte overhead
tinytext 0-255 1 byte overhead
text 0-65535 byte 2 byte overhead
mediumtext 0-16M  3 byte overhead
longtext 0-4Gb 4byte overhead

注意:

雖然text字段會把超過768字節的大部分數據溢出存放到硬盤其他空間,看上去是會更加增加磁盤壓力.但從處理形態上來講varchar大於768字節後,實質上存儲和text差別不是太大了.因爲超長的varchar也是會用到溢出存儲,讀取該行也是要去讀硬盤然後加載到內存,基本認爲是一樣的。另外從8000byte這個點說明一下:對於varcahr, text如果行不超過8000byte(大約的數,innodb data page的一半) ,overflow不會存到別的page中。
----------------------------------------


差異點:
text字段,MySQL不允許有默認值。建立索引必須給出前綴索引長度.
varchar允許有默認值,對索引長度沒限制,

注意:

InnoDB引擎單一字段索引的默認長度最大爲767字節,myisam爲1000字節.例如字符編碼是utf8,那麼varchar的索引最大長度是256個字符.超出限制會導致索引創建不成功,轉而需要創建前綴索引.設置innodb_large_prefix=1可以增大限制,允許索引使用動態壓縮,但是表的row_format必須是compressed或者dynamic.可以使索引列長度大於767bytes,但是總長度不能大於3072 bytes.
----------------------------------------


總結
  根據存儲的實現:可以考慮用varchar替代tinytext
  如果需要非空的默認值,就必須使用varchar
  如果存儲的數據大於64K,就必須使用到mediumtext , longtext
  varchar(255+)和text在存儲機制是一樣的
  需要特別注意varchar(255)不只是255byte ,實質上有可能佔用的更多。


感謝吳炳錫老師指導

參考文章地址:http://wubx.net/varchar-vs-text/

https://blog.csdn.net/free_ant/article/details/52936756

https://blog.csdn.net/q3dxdx/article/details/51014357


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章