这个问题最早在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社区吧。