Mysql中的存储引擎之Innodb

289 阅读4分钟

这是我参与8月更文挑战的第19天,活动详情查看:8月更文挑战

在开始讲解innodb存储引擎之前,我们先了解下一些关于MySQL的基础的知识。

Mysql为什么要用B+树

  1. B+树非叶子结点存储索引,而叶子结点存储索引和数据,而mysql中一个结点的大小是和页的大小相等的,一个结点就是一页,那么非叶子结点如果仅存储索引的话,其该结点能存储的索引就会变多,从而下一层可以存储更多的索引,从而减少树高,减少I/O次数。

  2. 涉及范围查询的时候B+树只需要遍历叶子结点层就可以取得数据(因为叶子结点用了双向指针)。

Mysql聚簇索引和非聚簇索引

聚簇索引:将索引和数据存储放到一块,找到索引就找到了数据,innodb就是用了聚簇索引,其叶子结点存储了索引和数据。innodb查找时如果查找的条件如果不是聚簇索引中的字段,则通过辅助索引找到相应的索引key,然后再通过索引key获得相应的数据。

非聚簇索引:将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应行,myisam通过key_buffer把索引先缓存到内存中,当需要访问数据时(通过索引访问数据),在内存中直接搜索索引,然后通过索引找到磁盘相应数据,这也就是为什么索引不在key buffer命中时,速度慢的原因

image.png

Innodb存储引擎

Innodb事务的实现

innodb存储引擎是支持事务的。这里就得提一下事务的基本特性了:原子性、一致性、隔离性和持久性,简称ACID。那么innodb是如何支持事务的呢?

  1. innodb中通过undo log实现事务的原子性。(关于undo log可以看我的一篇文章Mysql中的日志
  2. 数据库层面的话,是通过原子性、隔离性以及持久性来完成一致性的,其中一致性是目的,而原子性、隔离性和持久性是手段。只有实现了这三个特性,一致性才能保证。
  3. 隔离性主要通过加锁和MVCC(多版本控制协议) 实现,其中MVCC中实现的关键点也是undo log。
    • 加锁主要是为了防止一个事务在操作时有另外的事务进行干扰。
    • MVCC则主要是在事务开始操作前进行一份数据快照的备份,并用这个备份给其他事务进行一致性读取
  4. 持久性主要是通过redo log实现的。

Innodb表存储主键key或具体索引数据

innodb存储引擎使用主键索引作为表的聚簇索引,聚簇索引的特点是非叶子节点存放主键作为查找关键字,叶子节点存放实际的数据记录本身(也称为数据页),从左到右以关键字的顺序,存放全部数据记录,故聚簇索引其实就是数据存放的方式,所以每个表只能存在一个聚簇索引,innodb存储引擎的数据表也称为索引组织表。

innodb之所以只在主键存具体数据的索引指针,是因为要支持事务,只要锁住主键索引就可以实现行级锁。

此外innodb中直接用主键进行查询时,其查找效率是最高的。如用非主键查询,则要先通过辅助索引进行查询,查询到相应的主键key,再通过主键key进行查询获得相应的数据

其非聚簇索引结构叶子节点为什么存储的是主键值?

1.保持一致性,当数据库表进行DML操作时,同一行记录的页地址会发生改变,因非主键索引保存的是主键的值,无需进行更改;

2.节省存储空间,因为Innodb数据本身就已经汇聚到主键索引所在的B+树上了, 如果普通索引还继续再保存一份数据,就会导致有多少索引就要存多少份数据。

创建索引的建议

由于二级索引中保存了主键值,所以索引主键值越小越好,以免二级索引占用的空间过大,一般建议使用int的自增列作为主键。

这样可以保证数据行是按顺序写入的,对于根据主键做关联操作的性能也会更好。

因为主键是顺序的,所以每一条记录都保存在上一条记录的后面,当前的页写满的时候,下一条记录就写在新的页中。

这样在读取数据的时候,就可以按顺序读取,充分利用了局部性的优势,大大提高了读取效率。