MySQL存储引擎InnoDB、索引和索引下推

admin 2024年10月3日15:24:00评论19 views字数 2777阅读9分15秒阅读模式

1、InnoDB简介

Mysql 5.5 及以前版本默认引擎是Myisam,Mysql5.5以后默认引擎是InnoDB。

InnoDB在性能、事务支持和容错能力等方面具有较好的特性,适合大多数应用场景。表数据文件本身按B+Tree组织的一个索引结构文件,由2个文件组成:表结构是*.frm 和索引+数据*.ibd。以下是InnoDB的主要优点和特性

1.1、支持事务(ACID)

InnoDB 支持 ACID(原子性、一致性、隔离性、持久性)事务,确保数据在并发环境中的一致性和可靠性。

原子性 (Atomicity):通过回滚日志(Undo Log)来确保事务的原子性,当事务回滚时,所有对数据的修改都可以被撤销。

一致性 (Consistency): 确保事务从一个一致的状态转移到另一个一致的状态。

隔离性 (Isolation):支持多种事务隔离级别(读未提交、读已提交、可重复读和可串行化),默认隔离级别是可重复读,使用多版本并发控制(MVCC)和间隙锁避免幻读。

持久性 (Durability):使用重做日志(Redo Log)确保数据的持久性,在系统崩溃后,重做日志可以恢复未提交的数据。

1.2、行级锁(Row-Level Locking)

InnoDB 采用行级锁而非表级锁,这提高了并发性能,允许多个事务同时对不同的行进行读写操作,减少了锁竞争。

1.3、自动崩溃恢复

InnoDB 使用日志(redo log 和 undo log)来支持崩溃恢复。在系统故障或崩溃后,可以通过日志文件恢复未提交的数据和事务,确保数据的持久性。

1.4、支持外键

InnoDB 支持外键约束,建立表与表之间的连接,实现数据之间的关联和参照完整性,可以保证数据的完整性。

1.5、聚簇索引(Clustered Index)

InnoDB 使用聚簇索引(主键索引),数据按主键顺序物理存储,每个表只能有一个聚簇索引,通过主键查找数据非常高效。

1.6、MVCC(多版本并发控制)

InnoDB 通过多版本并发控制(MVCC)实现高效的并发读写操作。MVCC主要通过Undo多版本链和Read View机制,来实现一行数据在并发场景下,不需要加锁保证读、写的数据隔离性。

Undo多版本链:MVCC通过为每行数据项维护多个版本来实现并发控制。当一个事务对数据进行修改时,它不会直接覆盖现有的数据,而是创建一个新的版本。这些不同数据版本形成了单向版本链。

Read View机制:在事务开始时,ReadView 并不会立即创建,而是等到第一次需要读取数据的时候。RR 隔离级别下,ReadView 只会在事务第一次读取数据时创建,并在整个事务中保持不变,保证事务的快照一致性。RC 隔离级别下,每次读取数据时都会创建新的 ReadView,保证事务读取到的是其他事务提交的最新数据。

MVCC通过从undolog多版本链的头部开始遍历,根据数据版本的事务ID,结合readview以及可见性的规则,判断哪些数据版本对当前事务是否可见。

2、InnoDB的存储架构

InnoDB采用页、区、段和表空间的层次结构管理数据。

页是所有数据的基本存储单元,每个页面(16KB)可以包含多行数据。

区是由 64 个连续的页构成,大小为 1MB,InnoDB 通过区分配空间,从而有效管理表的增长。

段是由多个区组成的逻辑空间,数据表的索引段和数据段都是由多个区组成。

表空间是数据和索引的物理存储位置,支持单独和共享两种方式,表的物理文件就是表空间文件。

3、InnoDB的索引

InnoDB的索引可分为聚簇索引(Clustered Index)和二级索引(Secondary Index)。聚簇索引又称为主键索引,二级索引是非聚簇索引。

3.1、聚簇索引(Clustered Index)

聚簇索引(主键索引)的数据按主键顺序物理存储,每个表只能有一个聚簇索引。如果没有主键可分两种情况,有唯一非空索引,以该索引作为聚簇索引,无唯一索引,生成一个6字节的隐藏列row_id作为聚簇索引,它会自动递增。

聚簇索引的值必须是唯一的,不能重复,且不能为 NULL。查询高效,因为数据按照主键顺序存储,尤其是在范围查询时,例如 where id between 1 and 50

3.2、二级索引(Secondary Index)

二级索引是非聚簇索引,存储索引列值和主键值的对应关系,不直接存储数据,一张表可以创建多个二级索引。

使用二级索引查询时,通常先通过二级索引找到主键值,再根据主键值回表找到对应的数据行,也就是回表。除非查询是覆盖索引,即查询的所有字段都在二级索引中。

你是否会有疑问为什么 InnoDB 的二级索引存储主键值?

主要有两个原因:

(1) 主键的稳定性:主键是唯一且固定的,数据行的物理存储地址可能会因数据页的拆分或合并发生变化。通过存储主键值,InnoDB 只需在数据移动时更新聚簇索引,不需更新所有的二级索引。

(2) 聚簇索引的设计:由于表数据是按照主键顺序存储,使用主键值可以快速定位到数据所在的页和位置,通过主键回表效率较高。

4、索引下推

索引下推是MySQL 5.6 引入的一种查询优化技术,能够减少回表操作次数,提升查询效率。适用于二级索引的查询优化,不适用于主键索引,MySQL 默认开启索引下推。

4.1、原理与作用

原理是将 WHERE 子句中的一部分过滤条件下推到索引扫描阶段,在索引扫描时过滤掉不符合条件的记录,再回表读取完整的数据行,减少回表次数。

作用是减少不必要的回表操作,优化二级索引的查询效率,提高查询性能。

4.2、适用场景

索引下推适用场景:复合索引、范围查询,范围查询就是涉及范围查询的场景(如 >、<、BETWEEN),单列索引也不适合。

索引下推只适用于二级索引,因为主键索引和二级索引的存储结构不同。

主键索引是聚簇索引,主键索引的叶子节点直接存储完整的行数据,所有过滤条件都是在读取数据时一起应用,不需要回表操作,索引下推没有优势。

二级索引是非聚簇索引,存储索引列和主键值的对应关系,查询时需要先通过索引定位到主键值,再根据主键值去回表获取完整的数据,索引下推提前应用部分过滤条件,减少不必要的回表操作。

5、索引最佳实践

(1) 全值匹配。

(2) 最左前缀法则,如果索引了多列,要遵守最左前缀法则,查询从索引的最左前列开始并且不跳过索引中的列。

(3) 不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),否则会导致索引失效而转向全表扫描。

(4) 存储引擎不能使用索引中范围条件右边的列。

(5) 尽量使用覆盖索引,减少 select * 语句。

(6) like以通配符开头('%abc...')索引失效会变成全表扫描操作。

(7) 字符串不加单引号索引失效。

6、我的公众号

敬请关注我的公众号:大象只为你,持续更新技术知识......

原文始发于微信公众号(大象只为你):MySQL存储引擎InnoDB、索引和索引下推

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年10月3日15:24:00
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   MySQL存储引擎InnoDB、索引和索引下推https://cn-sec.com/archives/3229071.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息