获取 MySQL innodb B+tree 的高度的方法

前言

MySQL 的 innodb 引擎之所以使用 B+tree 来存储索引,就是想尽量减少数据查询时磁盘 IO 次数。树的高度直接影响了查询的性能。一般树的高度在 3~4 层较为适宜。数据库分表的目的也是为了控制树的高度。那么如何获取树的高度呢?下面使用一个示例来说明如何获取树的高度。

示例数据准备

建表语句如下:

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) CHARACTER SET latin1 DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `name` (`name`),
  KEY `age` (`age`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

表中插入100万条数据。数据如下:

mysql> select * from user limit 2\G
*************************** 1. row ***************************
  id: 110000
name: ab
 age: 100
*************************** 2. row ***************************
  id: 110001
name: ab
 age: 100
2 rows in set (0.00 sec)

通过查询相关数据表获取树的高度

以 MySQL5.6 版本为例说明如何获取树的高度。

首先获取 page_no

mysql> 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 and b.name='test/user';
+-----------+---------+----------+------+-------+---------+
| name      | name    | index_id | type | space | PAGE_NO |
+-----------+---------+----------+------+-------+---------+
| test/user | PRIMARY |       22 |    3 |     6 |       3 |
| test/user | name    |       23 |    0 |     6 |       4 |
| test/user | age     |       24 |    0 |     6 |       5 |
+-----------+---------+----------+------+-------+---------+
3 rows in set (0.00 sec)

page_no 是索引树中Root页的序列号。其它各项的含义可以参照:
https://dev.mysql.com/doc/refman/5.6/en/innodb-sys-indexes-table.html

再读取页的大小

mysql> show global variables like 'innodb_page_size';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| innodb_page_size | 16384 |
+------------------+-------+
1 row in set (0.00 sec) 

最后读取索引树的高度

$ hexdump -s 49216 -n 10 ./user.ibd
000c040 0200 0000 0000 0000 1600
000c04a

可以发现 PAGE_LEVEL 为 0200,表示这棵二级索引树的高度为 3。后面的 1600 是索引的 index_id 值。十六进制的 16 转换为十进制数字是 22。这个 22 正好就是上面主键的 index_id。
上面 hexdump 命令中 49216 是怎么算出来的?公式是 page_no * innodb_page_size + 64。
3*16384+64=49216

我们在用这个方式查看下其他两个索引的高度。

$ hexdump -s 65600 -n 10 ./user.ibd
0010040 0100 0000 0000 0000 1700
001004a
$ hexdump -s 81984 -n 10 ./user.ibd
0014040 0200 0000 0000 0000 1800
001404a

可见,name 索引的高度是 2,age 索引的高度是 3。

根据索引的结构估算

如果你没有数据库服务器的权限。自己也可以根据数据库索引结构进行估算树的高度。
根据 B+Tree 结构,非叶子节点存储的是索引数据,叶子节点存储的是每行的所有数据。
非叶子节点每个索引项的大小是,数据大小+指针大小。假设指针大小为 8 个字节。每页不会被占满,预留1/5的空隙。下面我们估算下 name 和 age 两个索引的高度。

name 索引高度估算

非叶子节点每页存放的索引项数量。每页大小是 16k。name 的值为 ab。占2个字节。每项数据大小是 2+8=10字节。每页能存放的索引项数量是 16384 * 0.8 / 10 = 1310 个。
叶子节点每页存放的索引数量。每页大小是 16k。每项数据大小是 4+2+8=14 个字节。没页能存放的索引数量是 16384 * 0.8 / 14 = 936 个。
两层能存放 1310*936=1226160 个数据记录。可见120万条记录以下,树的高度为2。

age 索引高度估算

非叶子节点每页存放的索引项数量。每页大小是 16k。age 的类型为 int。占4个字节。每项数据大小是 4+8=12字节。每页能存放的索引项数量是 16384 * 0.8 / 12 = 1092 个。
叶子节点每页存放的索引数量。每页大小是 16k。每项数据大小是 4+4+8=16 个字节。没页能存放的索引数量是 16384 * 0.8 / 16 = 819 个。
两层能存放 1092*819=894348 个数据记录。可见90万条记录以下,树的高度为2。100万条为 3 层。

其它工具

还有一个小工具可以查看。InnoDB 表空间可视化工具innodb_ruby

以上就是获取 MySQL innodb 的 B+tree 的高度的示例的详细内容,更多关于MySQL innodb 的 B+tree 的资料请关注我们其它相关文章!

(0)

相关推荐

  • MySQL数据库innodb启动失败无法重启的解决方法

    问题介绍 电脑在使用过程中死机,重启后发现mysql没有启动成功,查看错误日志发现是innodb出现问题导致mysql启动失败. 错误日志 $ mysql.server start Starting MySQL . ERROR! The server quit without updating PID file (/usr/local/var/mysql/fdipzonedeMacBook-Air.local.pid). 22:08:37 mysqld_safe Starting mysqld

  • MySQL修改innodb_data_file_path参数的一些注意事项

    前言 innodb_data_file_path用来指定innodb tablespace文件,如果我们不在My.cnf文件中指定innodb_data_home_dir和innodb_data_file_path那么默认会在datadir目录下创建ibdata1 作为innodb tablespace. 说明 在测试环境下没有设置过多的详细参数就初始化并启动了服务,后期优化的过程中发现innodb_data_file_path设置过小: root@node1 14:59: [(none)]>

  • MySQL Innodb 存储结构 和 存储Null值 用法详解

    背景: 表空间:INNODB 所有数据都存在表空间当中(共享表空间),要是开启innodb_file_per_table,则每张表的数据会存到单独的一个表空间内(独享表空间). 独享表空间包括:数据,索引,插入缓存,数据字典.共享表空间包括:Undo信息(不会回收<物理空间上>),双写缓存信息,事务信息等. 段(segment):组成表空间,有区组成. 区(extent):有64个连续的页组成.每个页16K,总共1M.对于大的数据段,每次最后可申请4个区. 页(page):是INNODB 磁盘

  • 简述MySQL InnoDB存储引擎

    前言: 存储引擎是数据库的核心,对于 MySQL 来说,存储引擎是以插件的形式运行的.虽然 MySQL 支持种类繁多的存储引擎,但最常用的当属 InnoDB 了,本篇文章将主要介绍 InnoDB 存储引擎相关知识. 1. InnoDB 简介 MySQL 5.5 版本以后,默认存储引擎就是 InnoDB 了.InnoDB 是一种兼顾了高可靠性和高性能的通用存储引擎.在 MySQL 5.7 中,除非你配置了其他默认存储引擎,否则执行 CREATE TABLE 不指定 ENGINE 的语句将创建一个

  • mysql更改引擎(InnoDB,MyISAM)的方法

    本文实例讲述了mysql更改引擎(InnoDB,MyISAM)的方法,分享给大家供大家参考.具体实现方法如下: mysql默认的数据库引擎是MyISAM,不支持事务和外键,也可使用支持事务和外键的InnoDB. 查看当前数据库的所支持的数据库引擎以及默认数据库引擎 数据库支持的引擎和默认数据库引擎代码: 复制代码 代码如下: show engines; 更改方式1:修改配置文件my.ini 我将my-small.ini另存为my.ini,在[mysqld]最后添加为上default-storag

  • 详解MySQL(InnoDB)是如何处理死锁的

    一.什么是死锁 官方定义如下:两个事务都持有对方需要的锁,并且在等待对方释放,并且双方都不会释放自己的锁. 这个就好比你有一个人质,对方有一个人质,你们俩去谈判说换人.你让对面放人,对面让你放人. 二.为什么会形成死锁 看到这里,也许你会有这样的疑问,事务和谈判不一样,为什么事务不能使用完锁之后立马释放呢?居然还要操作完了之后一直持有锁?这就涉及到 MySQL 的并发控制了. MySQL的并发控制有两种方式,一个是 MVCC,一个是两阶段锁协议.那么为什么要并发控制呢?是因为多个用户同时操作 M

  • 简单了解mysql InnoDB MyISAM相关区别

    前言 mysql支持很多表类型的表(即存储引擎),如myisam.innodb.memory.archive.example等.每种存储引擎都有自己的优点和缺点,充分的理解每种存储引擎,有助于合理的使用它们.有人认为在同一个数据库中使用多种存储引擎很影响性能,其实这是一种十分错误的想法.实际上,除非是非常简单的数据库,否则的话,只使用一种存储引擎,对应用程序的性能来说是一个十分糟糕的行为.对数据库了解的人会根据每张表的作用不同来选择适当的存储引擎,这才是正确的做法. 前面说过mysql的存储引擎

  • MySQL btree索引与hash索引区别

    在MySQL中,大多数索引(如 PRIMARY KEY,UNIQUE,INDEX和FULLTEXT)都是在BTREE中存储,但使用memory引擎可以选择BTREE索引或者HASH索引,两种不同类型的索引各自有其不同的使用范围. B树索引具有范围查找和前缀查找的能力,对于有N节点的B树,检索一条记录的复杂度为O(LogN).相当于二分查找. 哈希索引只能做等于查找,但是无论多大的Hash表,查找复杂度都是O(1). 显然,如果值的差异性大,并且以等值查找(=. <.>.in)为主,Hash索引

  • mysql报错:MySQL server version for the right syntax to use near type=InnoDB的解决方法

    本文实例讲述了mysql报错:MySQL server version for the right syntax to use near type=InnoDB的解决方法.分享给大家供大家参考,具体如下: 一.问题: 工作中使用sql语句建表时,mysql报了如下错误: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right

  • MySQL启动报错问题InnoDB:Unable to lock/ibdata1 error

    在OS X环境下MySQL启动时报错: 016-03-03T00:02:30.483037Z 0 [ERROR] InnoDB: Unable to lock ./ibdata1 error: 35 2016-03-03T00:02:30.483100Z 0 [Note] InnoDB: Check that you do not already have another mysqld process using the same InnoDB data or log files. 终端不断地重

  • 可以改善mysql性能的InnoDB配置参数

    而由于InnoDB是一个健壮的事务型存储引擎,已经有10多年的历史,一些重量级的互联网公司(Yahoo,Google Netease ,Taobao)也经常使用 我的日常工作也经常接触InnoDB,现在就InnoDB一部分可以改善性能的参数列举 1. innodb_additional_mem_pool_size 除了缓存表数据和索引外,可以为操作所需的其他内部项分配缓存来提升InnoDB的性能.这些内存就可以通过此参数来分配.推荐此参数至少设置为2MB,实际上,是需要根据项目的InnoDB表的

随机推荐