天天看點

MySQL實戰系列:大字段如何優化

線上發現一張表,1億的資料量,實體大小盡然驚人的大,1.2t 最終發現,原來有很多字段,10個varchar,1個text 這麼大的表,會給運維帶來很大的痛苦:ddl咋辦?恢複咋辦?備份咋辦?
藍圖: database --> tablespaces --> pages --> rows --> columns
MySQL實戰系列:大字段如何優化
MySQL實戰系列:大字段如何優化
資料頁(b-tree node) undo頁(undo log page) 系統頁(system page) 事務資料頁(transaction system page) 插入緩沖位圖頁(insert buffer page) 未壓縮的二進制大對象頁(uncompressd blob page) 壓縮的二進制大對象頁(compressd blob page)
預設16k(若果沒有特殊情況,下面介紹的都是預設16k大小為準) 一個頁内必須存儲2行記錄,否則就不是b+tree,而是連結清單了
MySQL實戰系列:大字段如何優化
MySQL實戰系列:大字段如何優化
MySQL實戰系列:大字段如何優化
不常用
MySQL實戰系列:大字段如何優化
不管是char,還是varchar,在compact row-format格式下,null都不占用任何存儲空間 在多位元組字元集的情況下,char vs varchar 的實際行存儲基本沒差別 char不管是否是多字元集,對未能占滿長度的字元還是會填充0x20 規範中:對char和varchar可以不做要求
當實際長度大于255的時候,變長字段長度清單需要用兩個位元組存儲,也就意味着每一行資料都會增加1個位元組 實測下來存儲空間增長并不算大,且性能影響也不大,是以,盡量在256之内吧
char的最大限制是: n<=255 varchar 的最大限制是: n<=65535 , 注意官方文檔說的是n是位元組,并且說的是一行的所有字段的總和小于65535,而varchar(n)中的n表示的是字元。 測試後發現,65535并不是最大限制,最大的限制是65532

為什麼會有行溢出off-page這個概念呢

假設建立了一張表,裡面有一個字段是a varchar(30000) , innodb的頁才16384個位元組,如何存儲的下呢?是以行溢出就來了嘛

如何看出行溢出了?

可以通過姜承堯寫的工具檢視 其中溢出的頁有 uncompressed blob page: 243453

溢出有什麼危害

溢出的資料不再存儲在b+tree中 溢出的資料使用的是uncompress blob page,并且存儲獨享,這就是存儲越來越大的真正原因 通過下面的測試,你會發現,t_long 插入的資料僅僅比 t_short 多了幾個位元組,但是最終的存儲卻是2~3倍的差距

什麼情況下會溢出

原則:隻要一行記錄的總和超過8k,就會溢出。 是以:varchar(9000) 或者 varchar(3000) + varchar(3000) + varchar(3000),當實際長度大于8k的時候,就會溢出 是以:blob,text,一行資料如果實際長度大于8k會溢出,如果實際長度小于8k則不會溢出,并非所有的blob,text都會溢出

多列總和大字段 vs 一列大字段

多個大字段會導緻多次off-page
如果有多個大字段,盡量序列化後,存儲在同一列中,避免多次off-page 将text等大字段從主表中拆分出來,a)存儲到key-value中 b)存儲在單獨的一張子表中,并且壓縮 必須保證一行記錄小于8k
<a href="http://dev.mysql.com/doc/refman/5.7/en/innodb-storage-engine.html">http://dev.mysql.com/doc/refman/5.7/en/innodb-storage-engine.html</a> innobase 官方文檔 mysql技術内幕 innodb存儲引擎 --姜承堯