MySQL索引介绍

索引的定义

  • 扇区:磁盘存储的最小单位,扇区一般大小为512Byte。
  • 磁盘块:文件系统与磁盘交互的的最小单位(计算机系统读写磁盘的最小单位),一个磁盘块由连续几个(2^n)扇区组成,块一般大小一般为4KB。
  • MySQL页 : MySQL和磁盘交互的最小单位,相当于4个磁盘块,16KB
  • 顺序IO:按物理存储顺序连续读取/写入数据,预读机制有效,减少磁头寻道时间(对HDD特别重要)。
  • 随机IO:随机IO是跳跃式读写,访问不连续的数据块,HDD 磁头需要频繁移动,难以有效利用预读,SSD 表现更好但仍有性能损耗。

总结:数据库最大的性能损耗就在磁盘IO上,这也是Redis比MySQL快很多的最大原因。索引是依靠某些数据结构和算法来组织数据,尽最大可能去利用磁盘的的顺序IO,并减少IO的次数来优化数据库的访问速度。

MySQL的索引结构

通过索引的定义接下来看MySQL索引数据结构,是如何实现顺序IO,和减少IO访问次数。
MySQL的索引采用B+tree的数据结构,是一种平衡多路查找树(不是二叉,是多叉),最下层的称之为叶子节点,叶子节点的上层为非叶子节点。叶节点具有相同的深度,节点的数据 key 从左到右递增。

非叶子节:

  • 一个非叶子节点只存储多个索引键值和对应的指针,不存储实际数据记录,这些节点在磁盘上以页(Page,16KB)为单位进行存储。这样可以有效降低B+tree的层数,降低IO次数。
  • 一次IO读取可以读取更多的索引键值,大幅降低降低IO读取次数。(MySQL以页为单位和磁盘进行交互)

叶子节点:

  • 在聚簇索引中:存储完整的行数据(包含索引键值)
  • 在二级索引中:存储索引列的值 + 主键值
  • 双向链表结构,支持范围查找,可以沿着叶子节点的链表顺序遍历,避免从根节点查找,减少IO次数

索引的分类

  • 聚集索引 :每个表有且一定会有一个聚集索引,关键字为主键,没有指定主键则自动添加一个隐藏的rowid(4byte)作为主键,所以也叫主键索引
  • 非聚集索引(辅助索引):叶子节点存储索引字段和主键值,其他子节点只存储索引字段
  • 回表 因索引叶子节点只存储主键和索引字段,如果查询其他字段就需要再查询一次主键索引,这就是回表。

索引的缺点

  • 增加存储成本
    索引本身需要占用一定的存储空间。对于大型数据库表,索引文件可能会变得非常庞大。例如,一个包含大量文本字段的数据库表,若在多个列上建立索引,索引文件的大小可能会与数据表本身的大小相当,甚至超过数据表的大小。这就需要额外的磁盘空间来存储索引数据,增加了存储成本。
  • 降低写入性能
    在对数据表进行插入(INSERT)、更新(UPDATE)和删除(DELETE)操作时,数据库需要同时维护索引的正确性。这些额外的操作会增加写入操作的时间和资源消耗,从而降低写入性能。特别是在高并发的写入场景下,频繁地维护索引可能会导致性能瓶颈。

索引使用原则

  • 最左原则: 复合索引 (a,b,c ) 如果查询条件只有 c = ? 或 b = ? and c= ? 时不会走索引,只有使用最左边的a 为条件时才会走索引。
  • 前缀匹配:使用like时,% 在前会使索引失效,%在后时,只能使用部分索引。
  • 索引区分度:索引区分度 = count(distint 记录) / count(记录),索引区分度非常小就接近于全表扫描了,所以创建索引时要选择区分度高的。
  • in 查询 相当于多个 唯一记录检索,然后合并结果。
  • 当多个条件中有索引的时候,并且关系是and的时候,会走索引区分度高的。
  • 避免回表操作,在设计数据库时,需要根据业务场景评估是否需要创建聚簇索引或合适的二级索引,以减少回表操作。
  • 字符串索引列,查询条件为 和 int比较 会导致索引失效。
  • int 索引列,查询条件为 和字符串比较,索引不会失效。
  • 使用union 关键字代替 or 。
  • 索引字段,使用函数,索引无效。
  • 索引字段使用运算符,索引无效 id +1 = 2 无效 id= 2+1索引有效。
  • 使用索引优化排序,B+树 就是按照索引值排序的链表,查询的结果自带排序。
相关推荐
b78gb17 小时前
电商秒杀系统设计 Java+MySQL实现高并发库存管理与订单处理
java·开发语言·mysql
奥尔特星云大使17 小时前
CentOS 7 安装 MySQL 8
mysql·centos·mysql 8
lang2015092818 小时前
MySQL FIPS模式:安全合规全解析
mysql
一只叫煤球的猫20 小时前
建了索引还是慢?索引失效原因有哪些?这10个坑你踩了几个
后端·mysql·性能优化
呼哧呼哧.21 小时前
Spring的核心思想与注解
数据库·sql·spring
21号 11 天前
9.Redis 集群(重在理解)
数据库·redis·算法
爬山算法1 天前
Redis(73)如何处理Redis分布式锁的死锁问题?
数据库·redis·分布式
嘗_1 天前
sql特训
数据库·sql
wan5555cn1 天前
周末之美:慢下来,拥抱生活的温柔
数据库
yumgpkpm1 天前
华为鲲鹏 Aarch64 环境下多 Oracle 、mysql数据库汇聚到Cloudera CDP7.3操作指南
大数据·数据库·mysql·华为·oracle·kafka·cloudera