1. 程式人生 > >讓天下沒有難用的資料庫 » innodb中大欄位的限制

讓天下沒有難用的資料庫 » innodb中大欄位的限制

今天開發在匯入資料的時候報一個錯誤:

表結構大致如下:

發現匯入的資料單行長度較長。

檢視官方文件的解決辦法為:

Solution:
1.divide your table into small ones. If one table contain more than 10 text colums, and the data contain is a little bit long. this error will be thrown out.
2.modify InnoDB to MyISAM.

但為什麼會出現上面的解釋?

通過查詢發現為innodb的一個限制:

我們知道innodb的頁塊大小預設為16kb,表中資料是存放在B-tree node的頁塊中,但如果表中一行的資料長度超過了16k,這時候就會出現行溢位,溢位的行是存放在另外的地方,存放該溢位資料的頁叫uncompresse blob page。

還要考慮的一點是,innodb採用聚簇索引的方式把資料存放起來,即B+樹結構,因此每個頁塊中至少有兩行資料,否則就失去了B+樹的意義(每一個頁中只有一條資料,整個樹成為了一條雙向連結串列),這樣就得出了一行資料的最大長度就限制為了8k。

當插入的一行資料不能不能在一個數據頁塊中存放時,為了保證該頁至少能存放兩行資料,innodb將會自動部分資料溢位到另外頁中,一部分資料將存放在資料頁塊中,其大小為該列的前768位元組,同時接著還有偏移指向溢位頁。

如上面所說大欄位的前768位元組會存放在資料頁塊中,那麼如果有10個大欄位(如varchar(1000),text,blob同varchar同樣儲存前768位元組),同樣會超過一行資料8k的限制

10*768<8000,11*768>8000。如果插入的值超過8000位元組,則會報錯(BLOB或TEXT同理):

ERROR 1030 (HY000): Got error 139 from storage engine

測試如下:

插入10列資料(10*768<8000)可以插入:

插入11列資料(11*768>8000)報錯:

Text資料型別測試:

Blob資料型別測試:

明白了是怎麼一回事後,就可以解決出現問題了,減少varchar(1000)的欄位數量,或者改儲存引擎為myisam;還可以增加page_size的大小:如改為32k,64k。由於需求不好改動,資料庫的頁塊大小改變需要改動原始碼,瞭解該表以查詢為主,更新非常少,所以改為myisam儲存引擎:

可以看到myisam儲存引擎不受此限制。

從上面也可以看出,在mysql innodb儲存引擎表收到頁塊大小,資料以B+樹的方式組織資料,導致單行資料不能超過8k,從而影響了表中大欄位資料型別varchar,text,blob個數限制,在16k頁塊大小下,最好不要超過10個,在表設計中需要注意這個限制。

在innodb plugin的版本中,mysql引入了新的檔案格式:barracuda,梭魚;改檔案格式中擁有兩種新的行記錄:compressed,dynamic,這兩鍾格式對於BLOB資料完全採用行溢位方式,在資料頁中只佔用20位元組用於指向溢位頁。