深入理解Mysql原理-存储引擎InnoDB(二)

引言

      说到存储引擎,我们在上文说过mysql的存储引擎结构是可插拔的,目前主要有InnoDB、Myism、Memory(不常用)这些,而我们最常用的是InnoDB,我们会对比一下这几个存储引擎,并重点讲一下InnoDB。

1. 为啥我们常选用InnoDB

我们对主要存储引擎进行一下对比:

类型

InnoDB

Myisam

Memory

查询速度

支持事务

Y

N

N

数据结构

B+

B+

HASH

锁机制

行锁

表锁

表锁

数据压缩

N

Y

Y

支持外键

Y

N

N

    从上图我们可以看到,单纯说查询数据,InnoDB不如其他的,但我们日常对数据库的使用,多为读写频繁的场景,表锁对频繁写数据的场景是不能接受的,而数据操作的完整性是日常工作中又是常见要求,所以事务很重要,基于这两点导致我们基本上都会选用InnoDB,Mysql也把默认存储引擎设为InnoDB(Mysql5.5版本及之后)

2. InnoDB存储引擎是什么样子?

2.1 InnoDB 体系架构

InnoDB 主要包括了:内存池、后台线程以及存储文件

内存池是由多个内存块组成的,主要包括缓存磁盘数据、undolog、redolog 缓冲等;

后台线程包括Master Thread、IO Thread 以及 Purge Thread 等基础的执行线程;

存储结构文件一般包括表结构文件(.frm)、共享表空间文件(ibdata1)、独占表空间文件(ibd)以及日志文件(redolog、undolog 文件等)等。

 

2.2. 内存池

       为了减少频繁操作磁盘带来一定的性能瓶颈,提高整个数据库的读写性能Mysql中设计了内存缓冲池。

       客户端读取数据时,如果数据存在于缓冲池中,客户端就会直接读取缓冲池中的数据,否则再去磁盘中读取;对于数据库中的修改数据,首先是修改在缓冲池中的数据,然后再通过 Master Thread 线程刷新到磁盘上。

      理论上来说,缓冲池的内存越大越好。缓冲池中不仅缓存索引页和数据页,还包括了 undolog 页,插入缓存、自适应哈希索引以及 InnoDB 地锁信息等等。

InnoDB允许多个缓冲池实例,从而减少数据库内部资源的竞争,增强数据库的并发处理能力,

InnoDB存储引擎会先将redolog日志信息放入到缓冲区中,然后再刷新到redolog日志文件中。

8.0版本之后查询缓存被取消,其实也挺好理解,查询缓存被重复使用的概率较低,且占内存,多线程请求的情况下都先查询缓存,命中率不高反而影响效率。

2.3. 后台线程

        Master Thread 主要负责将缓冲池中的数据异步刷新到磁盘中,除此之外还包括插入缓存、undo 页的回收等,IO Thread 是负责读写 IO 的线程,而 Purge Thread 主要用于回收事务已经提交了的 undolog,Pager Cleaner Thread 是新引入的一个用于协助 Master Thread 刷新脏页到磁盘的线程,它可以减轻 Master Thread 的工作压力,减少阻塞。

2.4. 存储文件

       在 MySQL中建立一张表都会生成一个.frm 文件,该文件是用来保存每个表的元数据信息的,主要包含表结构定义。

在 InnoDB 中,存储数据都是按表空间进行存放的,默认为共享表空间,存储的文件即为共享表空间文件(ibdata)

3. InnoDB的索引数据结构为啥是B+树?

      我们在上面表格中展示InnoDB的默认数据结构是B+树,这时可能就有小伙伴要问了,为啥选B+树,是否有其他选择,我们下面就这个问题进行简化版推导分析:

      首先我们有哪些选择,考虑到要数据需要持久化到磁盘,支持快速存储和查询,链表、栈之类的不太符合,优先考虑树和Hash,Hash无法做范围匹配,所以我们可以从树里面看,

     树有哪些选择:二叉树、红黑树、AVL、B树、B+树等;如何取舍?重点分析它们对检索效率的影响,这个时候我们需要清楚一点:索引是存储在磁盘上的,影响查询的核心因素之一就是磁盘IO。

二叉树

 

 红黑树

树分为二叉树和多叉树,每个层级的一次检索都相当于一次IO,而随着数据量增大,相比多叉树,二叉树的的层级将不可控,IO次数增多,效率也就没法保证,所以重点考虑、B树、B+树这种多叉树。

3.1 接下来我们就重点讨论B树和B+树:

B树结构如下:

 B树是多叉平衡树,每个阶段可以存储多个数据,而且每个节点不止两个节点,可以有多个节点,B数的每个节点都可以存放着索引和数据,也就是说并非只有叶子节点存放数据,数据遍布整个数结构,搜索可能在非叶子节点结束,最好的情况是O(1)。

B+树,结构如下

B+树结构上和B树类似,也是多叉树,区别在于:

1.数据只会存储在叶子节点,所以最好的查询效率O(2),比B树多一次。

2.叶子节点中有下个叶子节点的指针,整个叶子节点形成一个双向链表。

对比我们发现,B树和B+树最大的区别在于上级节点是否包含数据,既数据是否全部存储在叶子节点,虽然最优情况下的查询效率B树还好于B+树,但从mysql的选择上来看B+貌似好一些

为啥数据存储的位置问题会带来这种影响

这里我们就要插一个小知识点了,计算机局部性原理:当一个数据被用到时,其附近的数据也通常会马上被使用

      根据这一原理为减少IO,Mysql设计了按页预读的机制,即每次读取会顺序读取多页数据放到内存(一个页的大小,通常是16K),也就说我们的索引数据也是按页存储按页读取的

我们来假设一个场景(以下都是粗略计算,理解这个意思就行):

现在有一批数据,id(主键)大小都为1个字节,数量大小为1kb,

1. 用B树存储,一页差不多能存15个,三层的B树约15*15*15,约3000多数据,

2. 用B+树的话,索引页能存1000多,按1000算吧,叶子节点也就是数据页能存16个,三层的B+树能存1000*1000*16,约1600万数据;

那也就是说在数据量大一些、数据大小未知的情况下,按页存储读取,B树的层级也是不可控的,IO消耗不可控,而B+树则好的多,而且其叶子节点链表的设计也在顺序读取时比较省力

4.InnoDB为啥能支持事务而Myisam没有?

在对比的时候我们说了InnoDB的一大优势是支持事务,支持行锁,其实他俩有点相辅相成的,因为有行锁所以方便支持事务,而Myisam是不支持这些,虽然他俩的索引数据结构都是B+树,

为什么?

1. 不实现:这就是历史原因了,场景也不同,Myisam的更适用读,速度快,锁会影响效率。

2. 不方便实现:在这我们需要说一下另外一个概念:聚簇索引和非聚簇索引。

聚簇索引:将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据

非聚簇索引:又称辅助索引,将数据与索引分开存储,索引结构的叶子节点指向了数据对应的位置。

我们常说InnoDB使用的是聚簇索引,其实是不准确的,它其实既有聚簇索引又有非聚簇索引,及默认的主键索引(可设置)是聚簇索引,其他的是以叶子节点存储主键信息的非聚簇索引

Myisam使用的是非聚簇索引,叶子节点不存储具体数据,存储的事数据的存储位置。聚簇索引是数据物理有序的,非聚簇索引是逻辑有序,物理无序的,Myisam实现数据锁定代价会大一些。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值