最近在數(shù)據(jù)庫(kù)優(yōu)化的時(shí)候,看到一些表在設(shè)計(jì)上使用了text或者blob的字段,單表的存儲(chǔ)空間已經(jīng)達(dá)到了近100G,這種情況再去改變和優(yōu)化就非常難了
一、簡(jiǎn)介
為了清楚大字段對(duì)性能的影響,我們必須要知道innodb存儲(chǔ)引擎的處理方式:
1、一些知識(shí)點(diǎn)
1.1 在InnoDB 1.0.x版本之前,InnoDB 存儲(chǔ)引擎提供了 Compact
和 Redundant(Redundant 格式是為兼容之前版本而保留的)
兩種格式來(lái)存放行記錄數(shù)據(jù),compact 和 redundant 合稱(chēng)為Antelope (羚羊)
對(duì)于blob,text,varchar(5120)這樣的大字段,innodb只會(huì)存放前768字節(jié)在數(shù)據(jù)頁(yè)中,而剩余的數(shù)據(jù)則會(huì)存儲(chǔ)在溢出段中(發(fā)生溢出情況的時(shí)候適用),最大768字節(jié)的作用是便于創(chuàng)建前綴索引/prefix index,其余更多的內(nèi)容存儲(chǔ)在額外的page里,哪怕只是多了一個(gè)字節(jié)。因此,所有列長(zhǎng)度越短越好
大字段在InnoDB里可能浪費(fèi)大量空間。例如,若存儲(chǔ)字段值只是比行的要求多了一個(gè)字節(jié),也會(huì)使用整個(gè)頁(yè)面來(lái)存儲(chǔ)剩下的字節(jié),浪費(fèi)了頁(yè)面的大部分空間。如果有一個(gè)值只是稍微超過(guò)了32個(gè)頁(yè)的大小,實(shí)際上就需要使用96個(gè)頁(yè)面
擴(kuò)展存儲(chǔ)禁用了自適應(yīng)哈希,因?yàn)樾枰暾谋容^列的整個(gè)長(zhǎng)度,才能發(fā)現(xiàn)是不是正確的數(shù)據(jù)(哈希幫助InnoDB非常快速的找到“猜測(cè)的位置”,但是必須檢查“猜測(cè)的位置”是不是正確)。因?yàn)樽赃m應(yīng)哈希是完全的內(nèi)存結(jié)構(gòu),并且直接指向Buffer Pool中訪(fǎng)問(wèn)“最”頻繁的頁(yè)面,但對(duì)于擴(kuò)展存儲(chǔ)空間卻無(wú)法使用Adaptive Hash
1.2 MySQL 5.1 中的 innodb_plugin 引入了新的文件格式:Barracuda (梭子魚(yú))
,該文件格式擁有新的兩種行格式:compressed
和dynamic,兩種格式對(duì)blob字段采用完全溢出的方式,數(shù)據(jù)頁(yè)中只存放20字節(jié),其余的都存放在溢出段中,因此,強(qiáng)烈不建議使用BLOB、TEXT、超過(guò)255長(zhǎng)度的VARCHAR列類(lèi)型;
1.3 innodb的page大小默認(rèn)為16kb,innodb存儲(chǔ)引擎表為索引組織表,樹(shù)底層的葉子節(jié)點(diǎn)為一雙向鏈表,因此每個(gè)頁(yè)中至少應(yīng)該有兩行記錄,這就決定了innodb在存儲(chǔ)一行數(shù)據(jù)的時(shí)候不能夠超過(guò)8k,但事實(shí)上應(yīng)該更小,因?yàn)檫€有一些InnoDB內(nèi)部數(shù)據(jù)結(jié)構(gòu)要存儲(chǔ),5.6版本以后,新增選項(xiàng) innodb_page_size 可以修改,在5.6以前的版本,只能修改源碼重新編譯,但并不推薦修改這個(gè)配置