解析MySQL数据结构&&认识索引

134 阅读7分钟

Mysql运行机制

本文正在参加「技术专题19期 漫谈数据库技术」活动

sql执行过程

image.png

注:Mysql读取数据以数据页为单位,一页数据大小为16KB

模块与功能

  1. 连接器:管理连接,权限验证
    • 连接器负责跟客户端建立连接、获取权限、维持和管理连接
  2. 查询缓存:MySQL8.0以后删除了该功能
    • 执行过的语句会以KV形成缓存在内存中
    • 查询之前先查缓存
    • 不推荐使用缓存:数据表修改后,会删除所有相关缓存(表级别)
    • MySQL8.0版本删除了查询缓存功能
  3. 分析器:词法分析和语法分析 —— 做什么
    • 先做词法分析,识别SQL语句关键字
    • 再做语法分析,判断SQL是否符合语法
  4. 优化器:执行计划生成,索引选择 —— 怎么做
    • 决定如何使用索引以及关联表执行顺序
  5. 执行器:操作引擎,返回结果
    • 主要工作是校验权限、调用执行引擎
    • 首先校验用户对目标数据有无权限
    • 执行器以行为粒度,调用存储引擎执行sql
    • 在没有索引时,执行器会循环查询所有行
  • 例:select * from t where age = 10; age设置为普通索引 normal
    • 调用InnoDB引擎取表第一行数据,直接判断age是不是10,是则存入结果集,不是就跳过
    • 接着调用引擎获取下一行,重复判断逻辑,直到最后一行。返回结果集给客户端。
  1. 存储引擎:存储数据,提供读写接口
    • MyISAM
      • MYSQL 5.5.5之前默认存储引擎
      • 插入数据快
      • 不支持事务
      • 适用于查询效率要求高的
    • InnoDB
      • MYSQL 5.5.5之后默认存储引擎
      • 支持事务、外键
      • 支持崩溃修复能力和并发控制
    • Memory
      • 所有数据都在内存中,速度快
      • 数据安全性差
      • 适用于临时表
    • Archive
      • 数据压缩,空间利用率高
      • 插入速度快
      • 不支持索引,查询性能差
      • 适用于日志信息归档

存储结构和索引详解

存储结构

image.png

  1. 表空间 table space 包含了许多段;叶子节点段、非叶子节点段、rollback
    • 表空间指的是数据表在硬盘上的存储空间
      • 系统表空间 —— 系统用户都可以使用
      • 独立表空间 —— 独立使用
    • 每个表的数据默认放在独占表空间(ibd文件)
  2. 段 segment 包含了许多区
    • 数据段:B+树的叶子节点
    • 索引段:B+树的非叶子节点
    • InnoDB中,段由存储引擎自动管理
  3. 区 extent 区是页的分组,一个区包含了64个页 64*16 = 1024kb = 1mb
    • 区是由连续页组成的空间,大小为 1MB
    • 一次从磁盘申请4-5个区
  4. 页 page 一个页包含16kb数据
    • 页是InnoDB中磁盘读写的最小逻辑单位,默认为16KB
    • 一个数据页就是一个B+树的节点(B+Tree Node)
    • 页的大小充分考虑了机械硬盘和SSD的最小单元(512B和4KB), 16KB是它们最小公倍数

image.png

  1. 行 row
  2. InnoDB中的变长列
    • 长度不固定的数据类型
      • VARCHAR
      • VARBINARY
      • BLOB
      • TEXT
  3. 行溢出数据
    • 由于InnoDB每个数据页容量有限,导致数据字段也是有限的
    • 当数据字段过大时,InnoDB会使用行溢出机制
    • 行溢出机制会把超长字段放入单独开辟的数据页
      • 将超长字段指针指向新开辟的BLOB页
  4. 行记录格式
  • InnoDB行记录格式主要分为两个时代
    • Redundant / Compact (Antelope文件格式)
    • Dynamic / Compressed (Barracuda文件格式)
  • Redundant MySQL5.0之前的默认是Row Format
    • 这里的col 1 2 记录的是字段的偏移量
    • Header 存的是一些元数据,例如列的数量、偏移量单位、下一记录指针
    • RowID 当数据库表没有建立索引,默认利用RowID建立索引,这是一个隐藏主键
    • TxId 是事务ID
    • Roll Pointer 是回滚指针

image.png

  • Compact MySQL5.1默认Row Format 对原来的Redundant 做了优化
    • 所有变长字段放在变长字段长度表
    • NULL标志位用于记录某列为控

image.png

  • Dynamic MySQL5.1默认Row Format

image.png

  • Compressed
    • 物理结构上与Dynamic类似
    • 对表的数据行使用zlib算法进行了压缩存储
    • 可以节约40%左右空间但对CPU的压力较大

索引详解

  1. 主流索引查找算法
  • 线性查找 Linear Search
    • 时间复杂度 O(n)
    • 从第一个数据开始,逐个匹配
    • 效率低
  • 二分查找 Binary Search
    • 时间复杂度 O(logN)
    • 拿出有序数列中点位置作为比较对象
    • 根据中点数据大小选取一半数据作为新的数列
    • 每次缩小一半查找范围
    • 无法应对数据存储不连续问题
  • 二叉树查找 Binary Search Tree
    • 时间复杂度 O(logN)
    • 使用经典二叉树数据结构
    • 由根节点开始查找
    • 极端情况可能退化为链表,不平衡
  • 平衡二叉树 AVL Tree
    • 查找时与二叉搜索树相同
    • 增删改时,通过旋转操作,维护树的平衡
    • AVL树可以保证不会退化成线性查找
    • 节点存放数据少
  • B树 B Tree
    • 线性数据结构和树的结合
    • 通过多数据节点大大降低了树的高度
    • 不需要旋转就可以保证平衡
    • 查询连续数据较慢
  • B+树 B+ Tree
    • B+树由B树发展而来的一种数据结构
    • B+树所有数据均在叶子节点
    • B+树的所有数据形成一个线性表
    • 非叶子节点都是索引
  1. 为什么说InnoDB索引即数据?
  • InnoDB使用B+Tree作为索引数据结构
  • B+Tree高度一般为2-4层,查找速度非常快
  • InnoDB索引分为 聚簇索引(主索引)、辅助索引和联合索引
    • 聚簇索引
      • 在一颗B+Tree中,每个节点都是一个页,每次新建节点就会申请一个页空间
      • 同一层的节点之间,通过页的结构构成了一个双向链表
      • 非叶子节点,包括了多个索引行,每个索引行里存储索引键和指向下一层页面的指针
      • 叶子节点中存储了关键字和行记录,在节点内部(也就是页结构的内部)记录之间是一个单向的链表
      • 数据按照主键顺序存储
    • 辅助索引
      • 叶子节点并不包含行记录全部数据,叶子节点除包含键值以外包含了一个书签 bookmark
      • InnoDB引擎通过书签找到索引对应的行数据,成为回表查询
    • 组合索引
      • 遵循最左匹配原则
      • 组合索引单个索引值也可以生效,由于遵循最左匹配,建议将查询经常用到的索引字段放在组合索引的第一位,从而达到索引的优化。
    • 覆盖索引
      • 覆盖索引可以减少树的搜索次数,所以使用覆盖索引能提高查询效率,达到优化查询目的。

image.png

image.png

组合索引

image.png

数据库执行计划分析与SQL优化

执行计划

  • 如何确定所写的SQL语句最优? 使用explain关键字可以模拟优化器执行SQL查询语句,分析查询语句效率以及原因。
  • 通过Explain可以分析出的指标
    • id 每个SELECT关键字对应的ID,唯一性
      • id也决定了执行顺序
      • 子查询ID自增,ID大的优先级高先执行
      • 如果ID为null 表示一个结果集无需使用ID查询,一般不常见
    • select_type 常见查询类型:SIMPLE、PRIMARK、UNION、SUBQUERY、DERIVED
    • table 表别名 没有别名就取原表名
    • type 表的访问方式,判断是否用到索引 常见类型(从优到劣) system > const > eq_ref > ref > range > index > ALL
      • system 不常见,表中只有一条记录(等于系统表)
      • const 表示通过索引一次扫描到,因为只匹配一行数据,mysql将这个查询转换成常量
      • eq_ref 唯一索引,索引键在表中位移。通常出现于 primary、unique
      • ref 查找和扫描混合,非唯一索引,匹配索引值的所有行
      • range 检索给定范围行
      • index 也算全表扫描 比all好点,因为index只遍历索引树(非叶子节点),index从索引中读取,all从硬盘读取
      • all 这个就是大家常说的全表扫描了,这个就不多做介绍,这个类型出现的越多代表sql性能越差
    • possible_keys 可能涉及的索引
    • key 实际使用到的索引
    • key_len 索引长度
    • ref
    • rows 扫描读取的数据行数
    • Extra 扩展信息