学习总结录 学习总结录
首页
归档
分类
标签
  • Java基础
  • Java集合
  • MySQL
  • Redis
  • JVM
  • 多线程
  • 计算机网络
  • 操作系统
  • Spring
  • Kafka
  • Elasticsearch
  • Python
  • 面试专题
  • 案例实践
  • 工具使用
  • 项目搭建
  • 服务治理
  • ORM框架
  • 分布式组件
  • MiniSpring
  • 设计模式
  • 算法思想
  • 编码规范
友链
关于
GitHub (opens new window)
首页
归档
分类
标签
  • Java基础
  • Java集合
  • MySQL
  • Redis
  • JVM
  • 多线程
  • 计算机网络
  • 操作系统
  • Spring
  • Kafka
  • Elasticsearch
  • Python
  • 面试专题
  • 案例实践
  • 工具使用
  • 项目搭建
  • 服务治理
  • ORM框架
  • 分布式组件
  • MiniSpring
  • 设计模式
  • 算法思想
  • 编码规范
友链
关于
GitHub (opens new window)
  • Java基础

  • Java集合

  • MySQL

    • MySQL深入01-查询语句
    • MySQL深入02-更新语句
    • MySQL深入03-事务隔离
    • MySQL深入04-深入浅出索引
    • MySQL深入05-全局锁、表锁、行锁
    • MySQL深入06-事务隔离再探
    • MySQL深入07-普通索引和唯一索引
      • MySQL深入07-普通索引和唯一索引
      • 两种索引查询过程深入
      • 两种索引更新过程深入
      • Change Buffer的使用场景
      • 索引选择小结
      • 参考
    • MySQL深入08-为什么会选错索引
    • MySQL深入09-字符串字段加索引
    • MySQL深入10-脏页刷新
    • MySQL深入11-数据库表空间回收
    • MySQL深入12-count()
    • MySQL深入13-order by
    • MySQL深入14-正确显示随机消息
    • MySQL深入15-索引失效案例分析
    • MySQL深入16-查询一行数据执行慢
    • MySQL深入17-幻读
    • MySQL深入18-改一行语句锁问题
    • MySQL深入19-暂时提高数据库性能方案
    • MySQL深入20-这么保证数据不丢
    • MySQL深入21-主备一致的保证
    • MySQL深入22-高可用性的保证
    • MySQL深入23-备库延迟好几个小时
    • MySQL深入24-主库出问题,从库这么办
    • MySQL深入25-读写分离的过期读问题
    • MySQL深入26-判断数据库是否出问题
    • MySQL深入27-误删数据的处理方案
    • MySQL深入28-kill不掉的语句
    • MySQL深入29-查询对内存的影响
    • MySQL深入30-join深入
    • MySQL深入31-join语句优化
    • MySQL深入32-临时表深入
    • MySQL深入33-内部临时表何时使用
    • MySQL深入34-InnoDB和Memory
    • MySQL深入35-自增主键为什么不连续
    • MySQL深入36-insert语句的锁
    • MySQL深入37-如何快速复制一张表
    • MySQL深入38-grant和flush privileges
    • MySQL深入39-分区表
    • MySQL深入40-自增id用完如何处理
  • Redis

  • JVM

  • 多线程

  • 计算机网络

  • Spring

  • Kafka

  • Elasticsearch

  • Python

  • 面试专题

  • 知识库
  • MySQL
旭日
2023-03-31
目录

MySQL深入07-普通索引和唯一索引

# MySQL深入07-普通索引和唯一索引

普通索引:就是在创建索引时,不附加任何限制条件(唯一、非空等限制)。该类型的索引可以创建在任何数据类型的字段上。

唯一索引:就是在创建索引时,限制索引的值必须是唯一的。通过该类型的索引可以更快速地查询某条记录。

# 两种索引查询过程深入

两者在查询语句上的差异:

  • 普通索引查找到第一个满足条件的记录后,继续向后遍历,直到第一个不满足条件的记录 。
  • 唯一索引由于索引定义了唯一性,查找到第一个满足条件的记录后,直接停止继续检索。

那么这两者在查询过程中性能差距有多少呢?

InnoDB 的数据是按数据页为单位来读写的。也就是说,当需要读一条记录的时候,并不是将这个记录本身从磁盘读出来,而是以页为单位,将其整体读入内存。在 InnoDB 中,每个数据页的大小默认是 16KB。

由于引擎是按页读写的,那么查找到的记录所在的数据页是在内存中的。普通索引需要额外做的事情,就是找到下一个不满足条件的记录,而一般来说下一个不满足条件的记录也是在该数据页中。

如果这个记录刚好是这个数据页的最后一个记录,那么要取下一个记录,必须读取下一个数据页,这个操作会稍微复杂一些。

但是这个情况出现概率很低,所以在计算平均性能上,两者差异几乎微乎其微。

# 两种索引更新过程深入

在对两种索引在更新过程中性能差异探讨前,先了解一下change buffer。

当需要更新一个数据页时,如果数据页在内存中就直接更新,如果数据页还没有在内存中,在不影响数据一致性的前提下,InnoDB 会将这些更新操作缓存在 change buffer 中,这样就不需要从磁盘中读入这个数据页了。在下次查询需要访问这个数据页的时候,将数据页读入内存,然后执行 change buffer 中与这个页有关的操作。通过这种方式就能保证这个数据逻辑的正确性。

change buffer实际上是可以持久化的数据,它在内存中有拷贝,也会被写入到磁盘上。

显然如果更新操作能先记录在change buffer,减少磁盘读写,语句的执行速度就会明显的提升。通过这种方式能够避免占用内存,提高内存利用率。

下面我们来分析一下两者在更新语句的差异:

1、如果更新的目标页在内存中:

  • 对于唯一索引来说,找到对应的位置,判断到没有冲突,插入这个值,语句执行结束;
  • 对于普通索引来说,找到对应的位置,插入这个值,语句执行结束。

如果更新的目标页在内存中,比较下来,唯一索引只是多了一个判断,只会耗费微小的CPU时间。

2、如果更新的目标页不在内存中:

  • 对于唯一索引来说,需要将数据页读入内存,判断到没有冲突,插入这个值,语句执行结束;
  • 对于普通索引来说,则是将更新记录在 change buffer,语句执行就结束了。

将数据从磁盘读入内存涉及随机 IO 的访问,是数据库里面成本最高的操作之一。change buffer 因为减少了随机磁盘访问,所以对更新性能的提升是会很明显的。

为什么唯一索引不使用change buffer

对于唯一索引来说,所有的更新操作之前都会进行一次唯一性的判断,而这个判断就需要把数据页读入内存,既然数据页已经读入内存了,那么直接更新内存就行了,就不需要使用change buffer。

# Change Buffer的使用场景

change buffer对普通索引在更新过程的加速作用是通过把更新语句进行了缓存,减少了磁盘的读取。那么对于普通索引的所有场景,使用change buffer都能起到加速的作用吗?

将 change buffer 中的操作应用到原数据页,得到最新结果的过程称为 merge。除了访问这个数据页会触发 merge 外,系统有后台线程会定期 merge。在数据库正常关闭(shutdown)的过程中,也会执行 merge 操作。

所以merge的时候才是数据真正更新的时刻,而change buffer是将记录的变更操作缓存下来,如果在merge之前,change buffer记录的变更越多,那么change buffer的收益就越大。

现在有两个业务场景:

1、对于写多读少的业务,比如日志之类的。页面在更新之后查询的概率比较小,此时change buffer这张草稿纸就能得到充分利用。

2、对于写少读多的业务,如果change buffer这张草稿纸还没有记录几条更新操作,就会因为马上要访问这个数据页导致触发merge过程。这样随机访问 IO 的次数不会减少,反而增加了 change buffer 的维护代价。所以,对于这种业务模式来说,change buffer 反而起到了副作用。

# 索引选择小结

  • 如果是查询,普通索引和唯一索引几乎没有区别
  • 如果是更新,尽量选择普通索引
    • 如果是读少写多,就使用change buffer。
    • 如果是读多写少,就关闭change buffer。

# 参考

MySQL 实战 45 讲-极客时间 (opens new window)

#MySQL
上次更新: 2024/06/29, 15:13:44
MySQL深入06-事务隔离再探
MySQL深入08-为什么会选错索引

← MySQL深入06-事务隔离再探 MySQL深入08-为什么会选错索引→

最近更新
01
基础概念
10-31
02
Pytorch
10-30
03
Numpy
10-30
更多文章>
Theme by Vdoing | Copyright © 2021-2024 旭日 | 蜀ICP备2021000788号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式