varchar or blob:欄位型別的儲存和溢位條件

hotdog04發表於2015-03-09
遇到大欄位儲存的時候,是使用長varchar還是blob(text)?

行模式不同,行溢位的行為也不同:
下面介紹不同行模式的表現:
row format:
compact:
1、compact格式的首部是一個非空的變長欄位長度列表,按照列的順利逆序放置,
   當列長度<255的時候,用一個位元組表示;>255的時候用2個位元組表示,變長字
   段最大值2個位元組(mysql的varchar最大長度2的16次方=65535)
2、第二部分是NULL標誌位,表示該行是否有NULL值,用1表示。該部分的單位是
   bytes。
3、行記錄頭:固定佔用5個位元組(40位),分佈如下:
   1  未知
   1  未知
   1  deleted_flag 刪除標記
   1  min_rec_flag 為1,如果該記錄是預先被定為最小的記錄
   4  n_owned 改記錄擁有的記錄數
   13 heap_no 索引堆中該記錄的排序記錄
   3  record_type 記錄型別 000=普通 001=B+樹節點指標 010=informum
      011=superemum 1xx=保留
   16 next_recorder 頁中下一條記錄的相對位置:(innodb引擎在頁內部是通過鏈
      表來串聯各行記錄的)
4、資料記錄行:NULL不佔用該部分的任何資料(NULL除了佔用NULL標誌位,實際儲存
   不佔用任何空間) 每行行除了使用者定義的資料,還有兩個隱藏列:事務ID列(6位元組)和
  回滾指標列(7位元組),如果沒有定義主鍵,每行還會增加一個rowid列(6位元組)

5、使用 hexdump -C [-v] table.ibd驗證

redundant:
mysql5.0之前的行記錄格式,跟compact記錄格式不同:
NULL的varchar不佔用空間,而空的char需要佔用



compact和redundant行溢位:
1、如果一個能夠至少放入兩行,varchar就不會放到blob頁中,這個
   閾值是8098,超過閾值,資料頁儲存768個位元組,剩餘儲存到blob頁
  (實驗:py_innodb_page_info, create table t(a  varchar(9000)),
    repeat('a',8098))
2、blob(text)表也不是全部儲存到blob頁,只有超出限制(8098)才會放置
   到blob頁(實驗:同上); 當blob列發生行溢位的時候資料頁儲存
   768個位元組,剩餘的儲存的blob頁


compact、redundant統稱:antelope
compressed、dynamic統稱:barracuda

dyanmic,compressed格式:
溢位使用完全的行溢位模式(溢位閾值也是8098),在資料頁只存放20個位元組的指標,
實際的資料都存放到blob頁中。
compressed格式的另外一個功能就是儲存的行資料會使用zlib的演算法進行壓縮,
對blob,text,varchar這類的長型別能進行有效的儲存。



總上:
1、在儲存大欄位型別的時候使用blob(比如圖片等)
2、在需要建索引的時候使用varchar(blob不能建立索引,可以使用字首索引)
3、大欄位型別不能有預設值,有預設值的場合使用varchar
4、varchar有長度限制,表的所有varchar列之和不能超過65535
5、使用大欄位型別的時候,儘量使用的少,避免使用多個
6、儲存長字串的時候看varchar和blob好像沒有太大的效能差異(varchar是
   字元比較,blob是二進位制流對比效率會高一些)

參考:
http://www.percona.com/blog/2010/02/09/blob-storage-in-innodb/
《mysql技術內幕innodb儲存引擎》

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/20625855/viewspace-1453859/,如需轉載,請註明出處,否則將追究法律責任。

相關文章