MySQL性能优化之char、varchar、text的区别
參考:https://dev.mysql.com/doc/refman/8.0/en/string-type-overview.html?
?? ? 在存儲字符串時, 可以使用char、varchar或者text類型, 那么具體使用場景呢?
??????? 參考下面這個表結構:
?
1、 char長度固定, 即每條數據占用等長字節空間;適合用在身份證號碼、手機號碼等定。
2、 varchar可變長度,可以設置最大長度;適合用在長度可變的屬性。
3、 text不設置長度, 當不知道屬性的最大長度時,適合用text。
?
按照查詢速度: char最快, varchar次之,text最慢。
?
char:char(n)中的n表示字符數,最大長度是255個字符; 如果是utf8編碼方式, 那么char類型占255 * 3個字節。(utf8下一個字符占用1至3個字節)
?
varchar:varchar(n)中的n表示字符數,最大空間是65535個字節, 存放字符數量跟字符集有關系;
???? MySQL5.0.3以前版本varchar(n)中的n表示字節數;
???? MySQL5.0.3以后版本varchar(n)中的n表示字符數;
? PS:varchar實際范圍是65532或65533, 因為內容頭部會占用1或2個字節保存該字符串的長度;如果字段default null(即默認值為空),整條記錄還需要1個字節保存默認值null。
?????? 如果是utf8編碼, 那么varchar最多存65532/3 = 21844個字符。
?
text:
跟varchar基本相同, 理論上最多保存65535個字符, 實際上text占用內存空間最大也是65535個字節; 考慮到字符編碼方式, 一個字符占用多個字節, text并不能存放那么多字符; 跟varchar的區別是text需要2個字節空間記錄字段的總字節數。
PS: 由于varchar查詢速度更快, 能用varchar的時候就不用text。
?
最近有幾個同學問我varchar和text有啥別嗎,這個問題,以前說真的也沒太多的整理,以前遇到text在設計中就是盡可能的拆到另一個表中,保持主表盡量的瘦小,可以讓innodb bp緩存更多的數據。
今天借次機會系統整理一下,主要從存儲上,最大值,默認值幾個方面進行比較。
BTW: 從ISO SQL:2003上講VARCHAR是一個標準型,但TEXT不是(包括tinytext).varchar在MySQL 5.0.3之前只支持0-255byte, 在5.0.3之后才支持到0-65535byte.
從存儲上講:
- text 是要要進overflow存儲。 也是對于text字段,不會和行數據存在一起。但原則上不會全部overflow , 會有768字節和原始的行存儲在一塊,多于768的行會存在和行相同的Page或是其它Page上。- varchar 在MySQL內部屬于從blob發展出來的一個結構,在早期版本中innobase中,也是768字節以后進行overfolw存儲。- 對于Innodb-plugin后: 對于變長字段處理都是20Byte后進行overflow存儲 (在新的row_format下:dynimic compress)?
說完存儲后,說一下使用這些大的變長字段的缺點:
?
- 在Innobase中,變長字段,是盡可能的存儲到一個Page里,這樣,如果使用到這些大的變長字段,會造成一個Page里能容納的行 數很少,在查詢時,雖然沒查詢這些大的字段,但也會加載到innodb buffer pool中,等于浪費的內存。 (buffer pool 的緩存是按page為單位)(不在一個page了會增加隨機的IO)- 在innodb-plugin中為了減少這種大的變長字段對內存的浪費,引入了大于20個字節的,都進行overflow存儲, 而且希望不要存到相同的page中,為了增加一個page里能存儲更多的行,提高buffer pool的利用率。 這也要求我們, 如果不是特別需要就不要讀取那些變長的字段。?
那問題來了? 為什么varchar(255+)存儲上和text很相似了,但為什么還要有varchar, mediumtext, text這些類型?
(從存儲上來講大于255的varchar可以說是轉換成了text.這也是為什么varchar大于65535了會轉成mediumtext)
我理解:這塊是一方面的兼容,另一方面在非空的默認值上varchar和text有區別。從整體上看功能上還是差別的。
這里還涉及到字段額外開銷的:
- 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?
備注?overhead是指需要幾個字節用于記錄該字段的實際長度。
從處理形態上來講varchar 大于768字節后,實質上存儲和text差別不是太大了。 基本認為是一樣的。
另外從8000byte這個點說明一下: 對于varcahr, text如果行不超過8000byte(大約的數,innodb data page的一半) ,overflow不會存到別的page中。基于上面的特性可以總結為text只是一個MySQL擴展出來的特殊語法有兼容的感覺。
默認值問題:
- 對于text字段,MySQL不允許有默認值。 - varchar允許有默認值?
總結:
根據存儲的實現: 可以考慮用varchar替代tinytext 如果需要非空的默認值,就必須使用varchar 如果存儲的數據大于64K,就必須使用到mediumtext , longtext varchar(255+)和text在存儲機制是一樣的需要特別注意varchar(255)不只是255byte ,實質上有可能占用的更多。特別注意,varchar大字段一樣的會降低性能,所以在設計中還是一個原則大字段要拆出去,主表還是要盡量的瘦小總結
以上是生活随笔為你收集整理的MySQL性能优化之char、varchar、text的区别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NUMA的取舍与优化设置
- 下一篇: 如何修改Xshell默认存储路径