MySQL B+Tree具体落地形式
这里主要讲解的是MySQL根据B+Tree索引结构不同的两种存储引擎(MYISAM 和 INNODB)的实现。
首先找到MySQL保存数据的文件夹,看看MySQL是如何保存数据的:
进入到这个目录下,这个目录下保存的是所有数据库,再进入到具体的一个数据库目录下。就能够看到MySQL存储数据和索引的文件了。
这里我创建了两张表,user_innod和user_myisam,分别指定索引为innodb和myisam。对于每张表,MySQL会创建相应的文件保存数据和索引,具体如下:
从图中可以看出:
MYISAM存储引擎存储数据库数据,一共有三个文件:
Frm:表的定义文件。
MYD:数据文件,所有的数据保存在这个文件中。
MYI:索引文件。
Innodb存储引擎存储数据库数据,一共有两个文件(没有专门保存数据的文件):
Frm文件: 表的定义文件。
Ibd文件:数据和索引存储文件。数据以主键进行聚集存储,把真正的数据保存在叶子节点中。
MyISAM存储引擎
在MYISAM存储引擎中,数据和索引的关系如下:
如何查找数据的呢?
如果要查询id = 40的数据:先根据MyISAM索引文件(如上图左)去找id = 40的节点,通过这个节点的数据区拿到真正保存数据的磁盘地址,再通过这个地址从MYD数据文件(如上图右)中加载对应的记录。
如果有多个索引,表现形式如下:
所以在MYISAM存储引擎中,主键索引和辅助索引是同级别的,没有主次之分。
Innodb存储引擎
Innodb主键索引为聚集索引,首先简单理解一下聚集索引的概念:数据库表行中数据的物理顺序和键值的逻辑顺序相同。
Innodb以主键索引来聚集组织数据的存储,下面看看Innodb是如何组织数据的。
如上图中,叶子节点的数据区保存的就是真实的数据,在通过索引进行检索的时候,命中叶子节点,就可以直接从叶子节点中取出行数据。mysql5.5版本之前默认采用的是MyISAM引擎,5.5之后默认采用的是innodb引擎。
在innodb中,辅助索引的格式如下图所示?
如上图,主键索引的叶子节点保存的是真正的数据。而辅助索引叶子节点的数据区保存的是主键索引关键字的值。
假如要查询name = C 的数据,其搜索过程如下:
- 先在辅助索引中通过C查询最后找到主键id = 9.
- 在主键索引中搜索id为9的数据,最终在主键索引的叶子节点中获取到真正的数据。
- 所以通过辅助索引进行检索,需要检索两次索引。
回表: 在辅助索引中一次查询到主键的值后,再次回到主键索引查找数据的过程叫回表
之所以这样设计,一个原因就是:如果和MyISAM一样在主键索引和辅助索引的叶子节点中都存放数据行指针,一旦数据发生迁移,则需要去重新组织维护所有的索引。
InnoDB必有主键索引:
- 如果已定义主键,则直接选择主键作为主键索引
- 如果不存在主键,则使用不带有NULL值的唯一索引作为主键索引
- 如果也不存在不带NULL值的唯一索引,则选择内置的6字节长的ROWID作为主键索引(递增,不可被选用 < 此为与Oracle InnoDB的不同)
- InnoDB建议使用递增的主键
- 递增的主键,在插入时近似顺序写入,会有更高的效率。
- 数据页到达阈值时只需要分配新的页,不会导致页分裂,索引也更易于维护
缺点:在高并发工作负载时,可能导致间隙锁竞争,调优参数:innodb_autoinc_lock_mode
把Innodb 和 MYISAM区别放在一张图中看,就如下所示: