文章目录
Hash索引
底层原理 :类似于Java中的HashMap
,通过键值对(索引列为键,行指针为值)存储数据。通过行指针直接定位数据。
使用场景:主要用于等值查询,查询效率极高。
优缺点:
- 优点: hash索引只能用于等值比较(
=
),所以查询效率非常高 - 缺点: 不支持范围查询,也不支持排序,因为索引列的分布是无序的
支持引擎:Memory存储引擎支持显式Hash索引,但InnoDB仅支持自适应Hash索引(无法手动控制)。
sql
SET GLOBAL innodb_adaptive_hash_index = 1; -- 开启(默认开启)
理解: 你可以创建hash索引,但是不生效,会变成B-tree索引。
InnoDB 会根据情况(很多等值比较)自动调节为hash索引
聚簇索引与非聚集索引
按物理存储分类: InnoDB 的存储方式是聚集索引,MyISAM的存储方式是非聚集索引。
1. 聚簇索引(Clustered Index)
聚簇索引是一种存储方式,索引和数据存储在一起。每张表只能有一个聚簇索引,因为数据只能按照一种方式进行物理排序。
特点:
- 数据存储在索引的叶子节点: 聚簇索引的叶子节点存储了完整的行数据,因此查询索引的同时也读取了数据。
- 高效的单次查询: 对于基于主键的查询,由于数据和索引存储在一起,可以减少一次查询操作。
- 更新和删除开销较大: 由于数据存储方式与索引绑定,对数据的更新或删除需要维护索引树。
- InnoDB默认主键为聚簇索引: 在InnoDB引擎中,主键索引即为聚簇索引。
优缺点:
- 优点: 查询效率高,特别是按主键查询时。
- 缺点: 更新、插入时,维护索引树会增加系统开销;表只能有一个聚簇索引。
2. 非聚集索引(Non-Clustered Index)
非聚集索引是独立于数据存储的索引,其叶子节点存储指向实际数据的指针。
特点:
- 数据和索引分开存储: 非聚集索引的叶子节点存储的是主键值或数据页地址,而非行数据本身。
- 两次查询: 查询时需要先通过索引找到主键值或数据页地址,再通过主键回表查询完整数据(如果索引覆盖了查询字段则无需回表)。
- 维护成本低: 由于索引和数据分离,数据的增删改操作对索引的影响较小。
优缺点:
- 优点: 对更新、插入友好。
- 缺点: 查询效率比聚簇索引低,需要两次查询数据。
对比一下能更清楚的理解二者
特性 | 聚簇索引 | 非聚集索引 |
---|---|---|
数据存储位置 | 索引的叶子节点存储行数据 | 索引的叶子节点存储主键值或数据页地址 |
查询效率 | 高,单次查询即可读取数据 | 需要两次查询,效率相对低 |
索引个数 | 每个表只能有一个 | 可以有多个 |
更新和删除效率 | 较低,需维护索引树 | 较高,索引和数据分离 |
应用场景 | 查询频繁、按主键访问 | 辅助查询,非主键字段条件的查询 |
InnoDB 的存储分2个文件; MyISAM的存储分3个文件;
二级索引
二级索引就是非聚集索引,Mysql中除主键以外的都是二级索引。
主键索引的叶子结点 是所有相关数据,二级索引的叶子节点关联的是主键。
sql
CREATE TABLE users(
id INT NOT NULL,
name VARCHAR(20) NOT NULL,
age INT NOT NULL,
PRIMARY KEY(id)
);
新建一个以age字段的二级索引:
ALTER TABLE users ADD INDEX index_age(age);
MySQL会分别创建主键id的聚簇索引和age的二级索引:
回表与覆盖索引
回表
当非聚集索引的叶子节点无法直接满足查询需求时,需要通过主键值回到聚簇索引获取完整数据的过程称为回表。
回表查询流程:
- 从非聚集索引中查找目标主键值。
- 利用主键值到聚簇索引查找完整行数据。
- 返回查询结果。
ex:先找到age=35对应的id,带着id去主键索引找数据。
sql
SELECT * FROM users WHERE age=35;
覆盖索引
当非聚集索引的叶子节点能够完全满足查询需求 ,无需回表查询 时,就称为覆盖索引。
所以,在日常开发中,尽量不要select * ,需要什么查什么,如果出现覆盖索引的情况,查询会快很多。
ex: age这个索引列中已经包含id了,就不用回表,这样查询速度更快,性能更高。
sql
SELECT id FROM users WHERE age=35;
优势:
- 减少I/O操作: 不需要回表查询完整数据。
- 性能提升: 查询速度更快。
单列索引与联合索引
1. 单列索引
为单个字段创建的索引。
mysql会根据单列索引
字段的值进行排序,这里我假设张三排在李四前面,当索引列的值相同时,就会根据id排序,所以索引实际上已经根据索引列的值排好序了。
- 优点: 创建简单,适合单字段的查询。
- 缺点: 对多条件查询的优化有限。
2. 联合索引
为多个字段创建的复合索引,通常按照字段的优先级排序。
简单来说就是(name,age):先以name排序,name相同时再以age排序,如果再有其它列,依次类推,最后再以id排序。
最左前缀原则:
- 索引从左到右依次匹配,最左列必须出现在查询条件中才能生效。
- 只有连续匹配的列才会生效。
ex: (a,b,c): 查询条件只有a, ab, abc这三种组合条件,才会走联合索引。
联合索引的优点:
- 减少索引数量: 一个联合索引可替代多个单列索引,减少磁盘开销。
- 支持覆盖索引: 如果查询字段全部包含在联合索引中,可以避免回表。
- 筛选数据更精准: 多个条件联合过滤,提高查询效率。
使用场景:
- 单列索引:针对单字段频繁查询,例如状态字段、布尔值字段。
- 联合索引:针对多字段联合查询,特别是排序需求较高的场景。
总结
-
主键字段使用聚簇索引: 对于InnoDB表,默认主键即为聚簇索引,优先选择查询频繁的字段作为主键。
-
频繁查询字段加索引: 对查询频繁、过滤条件使用的字段单独加索引。
-
联合索引代替多单列索引: 优化查询效率时,考虑联合索引以支持覆盖索引和最左前缀匹配。
-
避免过多索引: 索引过多会增加插入、删除、更新的成本,且占用磁盘空间。
-
尽量使用覆盖索引: 避免
SELECT *
,只查询需要的字段。 -
考虑排序规则: 建表时选择合适的字符集和排序规则(如
utf8mb4_general_ci
)。 -
联合索引代替多单列索引: 优化查询效率时,考虑联合索引以支持覆盖索引和最左前缀匹配。
-
避免过多索引: 索引过多会增加插入、删除、更新的成本,且占用磁盘空间。
-
尽量使用覆盖索引: 避免
SELECT *
,只查询需要的字段。 -
考虑排序规则: 建表时选择合适的字符集和排序规则(如
utf8mb4_general_ci
)。
博客首页: 总是学不会.