一、聚簇索引
innoDB将表中数据按主键顺序构造成一颗B+树,叶子节点存放着整张表的行记录数据(索引组织表,即叶子节点就是数据页)。因为无法把数据行存在二个不同的地方,因此每张表只能有一个聚集索引(因此也只能有一个PRIMARY KEY)。
二、二级索引
叶子节点除了包含索引键值外,还包含了聚集索引键值。一张表可以存在多个辅助索引。通过辅助索引查找时,InnoDB通过辅助索引叶子节点的主键值,再通过主键索引找到完整的行。之所以叶子节点中存储的不是"行指针",而是主键值,这样的策略减少了当行移动或者数据页分裂时二级索引的维护工作。
三、插入缓冲
应用程序的插入行操作通常是按主键递增的顺序插入的,和聚集索引的结构一致,因此插入聚集索引通常都是顺序的,不需要随机读取。但是对于辅助索引,插入和更新操作影响的页并不是顺序的,因此会导致大量的随机I/O操作。
InnoDB的插入缓存机制解决了以上的问题,它会检查二级索引页是否在缓冲池中,如果在,InnoDB就直接对索引页应用变更。否则,InnoDB在insert buffer中记录变更,并周期性地合并同一索引页上的操作,大大提高了对二级索引执行插入操作的性能。
Q1:insert buffer 帮我们解决了什么问题?
举个现实中的例子来做说明,我们去图书馆还书,对应图书馆来说,他是做了insert(增加)操作,管理员在1小时内接受了100本书,这时候他有2种做法把还回来的书归位到书架上
1)每还回来一本书,根据这本书的编码(书柜区-排-号)把书送回架上
2)暂时不做归位操作,先放到柜面上,等不忙的时候,再把这些书按照书柜区-排-号先排好,然后一次性归位
用方法1,管理员需要进出(IO)藏书区100次,不停的登高爬低完成图书归位操作,累死累活,效率很差。
用方法2,管理员只需要进出(IO)藏书区1次,对同一个位置的书,不管多少,都只要爬一次楼梯,大大减轻了管理员的工作量。
关系数据库在处理插入操作的时候,处理的方法和上面类似,每一次插入都相当于还一本书,它也需要一个柜台来保存插入的数据,然后分类归档,在不忙的时候做批量的归位。这个柜台就是insert buffer。
Q2:insert buffer 有什么限制,为什么?
只对于非聚集索引(非唯一)的插入和更新有效。
为什么对于非聚集索引(非唯一)的插入和更新有效?
还是用还书的例子来说,还一本书A到图书馆,管理员要判断一下这本书是不是唯一的,他在柜台上是看不到的,必须爬到指定位置去确认,这个过程其实已经产生了一次IO操作,相当于没有节省任何操作。
所以这个buffer只能处理非唯一的插入,不要求判断是否唯一。聚集索引就不用说了,它肯定是唯一的,MySQL现在还只能通过主键聚集。
四、二次写
若说insert buffer带给InnoDB存储引擎的是性能,那么二次写带给带给innoDB存储引擎的是数据的可靠性。当数据库宕机的时候,可能发生在数据库正在写一个页面,而且这个页面只写了一部分的情况,我们称之为部分写失效。在InnoDB存储引擎未使用double write技术前,曾出现过因为部分写失效而导致数据丢失的情况。
也许有人会说写失效,可以通过重做日志来恢复,但是必须清楚的是,重做日志中记录的是对页的物理操作,如偏移量800,写‘aaaa‘记录。如果这个页本身已经损坏,再对其进行重做是没有意义的。这就是说,在应用重做日志前,我们需要一个页的副本,当写入失效发生时,先通过页的副本来还原该页,再进行重做,这就是doublewrite。
五、自适应索引
InnoDB存在一个监控索引查找的机制,当发现建立哈希索引可以提升查询效率时,便会自动创建,因此称之为自适应(adaptive)哈希索引。哈希索引的建立基于表上已存在的B+树,并且可只在那些经常访问的索引页上建立。