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的扇出來計算高度如下: