查看 InnoDB表中每個的索引高度
這個問題最早在Inside君的IMG微信群中進行討論,經過為期2周的討論,結合群內小伙伴的集體智慧,終于克服了這個問題。此問題的起源是很多小伙伴都會問Inside君,如何查看InnoDB的索引樹的高度,在我的書中 《MySQL技術內幕:InnoDB存儲引擎》 中,我寫到一般樹的高度在3~4層之間,但是并沒有給出證明的手段或者方法。InnoDB也沒有提供相應的視圖進行查看。其實明白InnoDB索引的構造,就能迅速得出索引的高度。
InnoDB是索引組織表,每個頁都包含一個PAGE_LEVEL的信息(見上圖右半部分),用于表示當前頁所在索引中的高度。默認葉子節點的高度為0,那么root頁的PAGE_LEVEL + 1就是這棵索引的高度。接下去的問題就是怎樣得到一張表所有索引的Root頁所在的位置呢?看過Inside君的 《MySQL技術內幕:InnoDB存儲引擎》 都知道(space,3)這個頁是聚集索引的root,并且在 《MySQL內核:InnoDB存儲引擎 卷1》 中也已經說過,Root頁的位置通常是不會更改的。那么其他索引的Root頁所在的位置呢?
其實官方提供了內部視圖來查看每個索引的Root頁,但可惜的是大部分DBA們都不知道,亦或許是因為覺得沒啥用吧,通過下面的SQL語句可以查出某這表對應索引的Root頁:
SELECT b.name, a.name, index_id, type, a.space, a.PAGE_NO FROM information_schema.INNODB_SYS_INDEXES a, information_schema.INNODB_SYS_TABLES b WHERE a.table_id = b.table_id AND a.space <> 0;
運行上述的SQL語句應該可以得到類似如下的結果:
其中(SPAE,PAGE_NO)就是索引的Root頁。SPACE,PAGE_NO對應的含義還不知道?那趕快來上Inside君的MySQL培訓班吧,最好的MySQL培訓班,過完年 深圳線下班 就將開啟。
有了這些信息就可以方便的定位啦,因為PAGE_LEVEL在每個頁的偏移量64位置出,占用兩個字節,通過hexdump這樣的工具就可以快速定位到所需要的樹高度信息:
root@test-1:~# hexdump -s 24640 -n 10 customer.ibd 00006040 00 02 00 00 00 00 00 00 00 47
查看customer表,24640表示的是3*8192+64(這里innodb_page_size設置為了8192,并非默認的16384),即第3個頁偏移量64位置開始讀取10個字節,但不是讀取2個字節就可以了嘛?其實因為后面8個字節對應的是index_id,就是上圖中看到的index為71的索引,這里PAGE_LEVEL為00 02,那么索引的高度就為3。
用同樣的方法可以查看customer表中i_c_nationkey的索引高度:
root@test-1:~# hexdump -s 32832 -n 10 customer.ibd 00008040 00 01 00 00 00 00 00 00 00 48
可以發現PAGE_LEVEL為00 01,表示這棵二級索引樹的高度為2。
雖然通常來說索引樹的高度為3~4層,但是極端情況下,比如數據量超級大,頁比較小,如4K,那么高度也是可能破4的。那么現在是不是可以來比比誰家的索引樹最高呢?
最后,IMG微信群會定期放出一些討論問題,非常具有挑戰,各位有態度的小伙伴要不要來挑戰看看呢?可惜微信群已滿,只能通過Inside君的邀請(Inside君的個人微信號:82946772),趕快加入這個有態度的IMG社區吧。