MySql資料儲存格式Compact及計算MySql的B+Tree高度

大海(lhc)發表於2022-02-08

1、MySql的compact行記錄格式

MySql從版本5.1以後預設使用的是compact行記錄格式。可以通過執行以下命令查詢到Row_format知悉InnoDB行記錄格式型別。

show table status like '要檢視的表名';

Compact行記錄格式如下,注意:一個頁中存放的行記錄資料越多,其效能就越高。

  • 變長欄位列表:按照列的順序逆序放置;若列的長度小於255位元組,用1個位元組表示;若列的長度大於255位元組,用2個位元組表示(MySql的庫表中varchar欄位最大長度限制為65535位元組);
  • null標誌位:表示改行記錄中是否有欄位的值是null;
  • 記錄頭資訊:5個位元組共40bit,分割成為多個標記,有兩個關鍵的地方,一個是代表是否已被刪除佔1bit,另一個代表頁中下一條記錄的相對位置佔16bit;

變長欄位列表的理解:假設建立了一張表如下:

create table student(
  id int(8) primary key,//自增   stuno
char(8),   stuname varchar(20),   stusex char(1),   stuaddress varchar(360) )

儲存了一行資料('20210001','tom','M','中國深圳'),那麼【變長欄位列表】儲存的就是0c 03,為什麼是0c是因為“中國深圳”在utf8下面一個漢字佔用3個位元組,所以共佔用12個位元組換成16進位制就是0c;stuname儲存的英文字元,一個字元佔用1個位元組共佔用3個位元組所以是03。倒序排列即0c 03

如果儲存了一行資料('20210001','tom','M','中國深圳中國深圳中國深圳中國深圳...中國深圳'),此處讓中國深圳重複30次存入studaddress欄位,那麼【變長欄位列表】儲存的就是01 68 03 。因為30箇中國深圳存在mysql中(utf8)共佔用(4*3)*30=360個位元組(轉為16進位制就是01 68);stuname儲存的英文字元,一個字元佔用1個位元組共佔用3個位元組所以是03。倒序排列即01 68 03 。

所以說【變長欄位列表】所佔位元組是可變的,當存了4個漢字時為0c 03佔用了2個位元組,當存了120個漢字時為01 68 03佔用了3個位元組

另外,在compact行記錄模式下,char和varchar的null值都不會佔用儲存空間。在mysql版本5之後,varchar(num)定義num代表字元,一個英文是一個字元,一箇中文也是一個字元,但是在utf8下面,英文佔用1個位元組,中文佔用3個位元組。

 

2、計算MySql的B+Tree高度

理解以上compact格式後,就會知道怎麼估算B+樹索引的高度了。

假設有3000萬條記錄,每條記錄5個欄位(以上面的student表為例,估算地址用20個漢字表示,其他都是英文或數字且英文的佔滿長度),平均下來每個條記錄大小估算如下4+8+20+1+20*3=63位元組,這是儲存的有效資料大小;【變長欄位列表】存的內容是3c 14佔用2個位元組;空記錄標記1個位元組;記錄頭資訊5個位元組;事務ID用6個位元組;隱藏列7個位元組;即每條記錄63+2+1+5+6+7=84位元組。

每頁大小是16KB,所以葉子節點大約需要3000萬*84/16=15750萬個,根據聚集索引知道,非葉子節點儲存主鍵和指標(頁的偏移量),假設指標大小是4位元組,那麼非葉子節點的最大扇出就是16KB/(4KB主鍵+4KB指標)=2048,如果按2048的扇出來計算高度如下:

 

 

相關文章