当前位置: 移动技术网 > IT编程>数据库>Mysql > 浅谈innodb的索引页结构,插入缓冲,自适应哈希索引

浅谈innodb的索引页结构,插入缓冲,自适应哈希索引

2017年12月12日  | 移动技术网IT编程  | 我要评论

physical structure of an innodb index

所有的innodb索引都是btree索引,索引记录保存在叶子上,默认的索引页大小是16k。当有新的记录插入时,innodb出于对将来的insert和update操作的考虑,会尝试留下1/16的空闲页大小。

如果索引记录是完全按照索引记录的大小顺序插入的,那么索引也将填满整个页大小的15/16,如果插入顺序完全随机,那么索引页基本上填充为1/2至15/16自建。如果填充因子低于1/2,innodb会尝试重建b-tree。

mysql5.6以后,可以通过innodb_page_size参数设置当前实例下每个索引页的大小,一旦设定,无法再更改回来。推荐的配置一般是16k,8k或者4k。另外假如一个mysql实例设置了不同于默认值的innodb_page_size a,那么将无法使用其他不同于a值的实例上的文件(比如做一个物理备份和恢复)

insert buffering

数据库应用通常按照主键顺序插入的,在这种情况下,因为聚集索引的顺序和这个主键值的顺序完全一致,insert操作将会减少很多的随机io。

另一方面,二级索引通常不是唯一的,那么在二级索引中插入数据时是一个相对随机的顺序。同样的,delete和update操作在影响数据页时,涉及到索引的变更,在二级索引上也并不是紧挨着的。这就导致了大量的随机io。

当插入一条记录,或者从非唯一的二级索引删除一条记录,innodb首先会去检查该二级索引页是否在缓冲池中。如果在缓冲池,innodb将会直接在内存中修改这个索引页。如果该索引也不在缓冲池,那么innodb将会将这个修改记录到插入缓冲,也就是insertbuffer。insert buffer通常都比较小,所以能够保证全部在缓冲池中,并且更新非常频繁。这个修改的进程就是change buffering(通常情况下,它只会只作用于insert操作,所以也被称为insertbuffering,而该数据结构就是insert buffer)

disk i/o for flushing the insert buffer

那么插入缓冲如何减少随机io的呢?每个一段时间,insert buffer会去合并在insertbuffer中的二级非唯一索引。通常情况下,它会合并n个修改到同一个btree索引的索引页中,从而节约了很多io操作。经测试,insertbuffer可以提高15倍的插入速度。

在事务提交后,insert buffer可能还在合并写入。所以,假如当db异常重启,reovery阶段,当有非常多的二级索引需要更新或插入时,insert buffer将可能花费很长时间,甚至几个小时。在这个阶段,磁盘io将会增加,那么就会导致disk-bound类型的查询有显著的性能下滑。

adaptive hash indexes

自适应哈希索引(ahi)使得innodb在缓冲池拥有足够的内存和某些工作负载下,看起来更像一个内存数据库,并且不会牺牲任何事务的特点和稳定性。这个特色由参数innodb_adaptive_hash_index控制,动态参数,默认为on表示打开自适应哈希索引,关闭ahi后内置哈希表将会被立马清空,而正常的操作依旧可以继续,只是直接通过访问b-tree索引。重新使能ahi后哈希表又会被重建。

通过观察搜素模式,mysql会利用index key的前缀建立哈希索引,这个前缀可以是任意长度,并且它可能仅仅是b-tree上的某些值,而不是整个b-tree。哈希索引通过检测,会在经常被访问的index pages上建立哈希索引。

如果一个表几乎大部分都在缓冲池中,那么建立一个哈希索引能够加快等值查询,通过将btree的索引值转换成一个排序指针。innodb有这个机制,可以监控索引的搜索情况,如果它注意到有些查询通过建立哈希索引可以优化查询,那么它会自动建立,所以说它是“自适应的”。

在某些工作负载下,通过哈希索引查找带来的性能提升价值远大于这个额外的监控索引搜索情况和保持这个哈希表结构所带来的开销。但某些时候,在负载较高的情况下,自适应哈希索引中添加的read/write 锁也会带来竞争,比如高并发的join操作。like操作和%的通配符同样不适用于ahi。如果工作负载不适合ahi,建议将它关闭,以免带来不必要的性能开销。因为mysql内部很难预示在一个特定的场合下ahi到底是否合适,推荐做一个实际工作负载的压测(有无ahi两种情况)。在5.6及以后版本中将会考虑让越来越多的工作负载最好disable掉自适应哈希索引,尽管目前而言它默认还是开启的。

哈希索引的创建往往是基于现有的b-tree,innodb可以通过观察b-tree的搜索情况建立任意长度的b-tree索引前缀的方式建立哈希索引。一个哈希索引可以只是部分的,仅包括b-tree index中最经常被访问到的页。

你可以通过观察show engine innodb status结果中的semaphores部分来决定是否使用自适应哈希索引。如果你看到很多线程都在btr0sea.c文件上创建rw-latch上waiting,那么建议关闭掉自适应哈希索引。本人曾经碰到过的一个case截图如下,典型的高并发模式下ahi引起的竞争,需要关闭ahi


以上这篇浅谈innodb的索引页结构,插入缓冲,自适应哈希索引就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

  • mysql解决时区相关问题

    前言:在使用 mysql 的过程中,你可能会遇到时区相关问题,比如说时间显示错误、时区不是东八区、程序取得的时间和数据库存储的时间不一致等等问题。其实,这些问题... [阅读全文]
  • MySQL8.0内存相关参数总结

    mysql理论上使用的内存 = 全局共享内存 + max_connections×线程独享内存。也就是:innodb_buffer_pool_size + in... [阅读全文]
  • mysql如何查询日期与时间

    前言: 在项目开发中,一些业务表字段经常使用日期和时间类型,而且后续还会牵涉到这类字段的查询。关于日期及时间的查询等各类需求也很多,本篇文章简单讲讲日期及时间字... [阅读全文]
  • 深入了解mysql长事务

    前言: 本篇文章主要介绍mysql长事务相关内容,比如说我们开启的一个事务,一直没提交或回滚会怎样呢,出现事务等待情况应该如何处理,本篇文章将给你答案。注意:本... [阅读全文]
  • 详解mysql DML语句的使用

    前言: 在上篇文章中,主要为大家介绍的是ddl语句的用法,可能细心的同学已经发现了。本篇文章将主要聚焦于dml语句,为大家讲解表数据相关操作。这里说明下ddl与... [阅读全文]
  • JDBC怎么连接数据库

    JDBC的快速入门(写这个东西是为了自己记一个笔记,或者为了方便别人应付作业)你要连接什么数据库就要下载什么类型... [阅读全文]
  • 高性能Mysql的逻辑架构和常见的存储引擎

    高性能Mysql的逻辑架构和常见的存储引擎

    前言: 为了充分发挥MySQL的性能并顺利地使用,就必须理解其设计。MySQL的灵活性体现在很多方面。例如,... [阅读全文]
  • 如何选择合适的MySQL日期时间类型来存储你的时间

    构建数据库写程序避免不了使用日期和时间,对于数据库来说,有多种日期时间字段可供选择,如 timestamp 和 datetime 以及使用 int 来存储 un... [阅读全文]
  • MySQL数据库使用规范总结

    导读: 关于mysql数据库规范,相信大家多少看过一些文档。本篇文章给大家详细分类总结了数据库相关规范,从库表命名设计规范讲起,到索引设计规范,后面又给出sql... [阅读全文]
  • 详解MySQL 外键约束

    官方文档:1.外键作用:mysql通过外键约束来保证表与表之间的数据的完整性和准确性。2.外键的使用条件 两个表必须是innodb表,myisam表暂时不支持... [阅读全文]
验证码:
移动技术网