【MySQL学习】索引——最左匹配原则 回表查询 MRR优化 聚集索引 非聚集索引 索引覆盖 索引失效

专门抽时间大致学习了MySQL的索引相关内容,下面做个总结

目录

索引的分类介绍

聚集索引和非聚集索引

 回表查询及两种优化(覆盖索引和MRR优化)

索引的适用场景

索引失效的常见场景


索引的分类介绍

索引主要分为四类:唯一索引,全文索引,聚集索引和非聚集索引。唯一索引(索引列中的值必须唯一,但可以为空),全文索引(对整张表建立索引,优先级高于其他任何索引),聚集(主键)索引(特殊的唯一索引,不能为空);非聚集索引(除聚集索引外的其他索引)。唯一索引和聚集索引又属于单列索引。

聚集索引和非聚集索引

聚集(主键)索引索引树的叶子节点存储数据行。物理地址按照索引存储。一张表只能存在一个聚集索引,且一定会存在一个聚集索引。若表存在主键,则该主键为聚集索引;若表不存在主键,则表中的唯一索引为聚集索引;若表中没有唯一索引,存储引擎自动生成一个隐藏的主键列作为聚集索引。

非聚集(辅助)索引索引树的叶子节点存储主键值。除聚集索引外,都可被称之为非聚集索引,其中最常见的就是组合索引(遵循最左匹配原则)。组合索引较单列索引较单列索引而言应用范围更广,若条件允许应尽量使用组合索引,因为其更容易形成索引覆盖。

最左匹配原则:假设abc三个字段构建组合索引,在构建组合索引时他们的排序规则:a是严格非减的,b只在a相等时非减,c只在ab相等时非减。所以在查询时也要遵循这样的排序规则,即(a,ab,abc)这三种字段排序是遵循最左匹配原则的。若查询时乱序,则索引字段无法保证严格递增,组合索引失效。

 回表查询及两种优化(覆盖索引和MRR优化)

回表查询:若待查询字段非主键,则会先通过非聚集索引查找到索引树叶子节点中储存的主键值,而后根据该主键值查询主键索引树上的数据。因为回表查询会额外查询辅助索引树,待查询数据量大的情况下,查询效率会大幅度降低。针对这个问题,引申出了两种查询优化:覆盖索引和MRR优化。

覆盖索引:避免回表查询的优化,将需要查询的数据组列作为索引列建立组合索引,可以直接查到数据,不需要先查主键再通过主键查数据,提高效率。

优点: ①索引条目远少于数据行条目,极大减少数据访问量。②索引是按索引列顺序存储的,和MRR优化一样将随机IO转成顺序IO。③辅助索引可以覆盖查询的话就不需要二次查询(调用主键索引)。④一些存储索引在内存中缓存索引,在操作系统中存放数据,如果只需要查询索引表,则少了一次调用系统的消耗。

MRR优化:因为查询多条结果集时,磁盘上大量的随机IO会大大降低查询效率,所以通过回表查询先将查询到的所有主键值储存到缓存中,而后通过排序将随机IO优化为顺序IO,使得寻址磁臂只需要一次遍历就可查询出所有所需数据。

随机IO:所需的数据随机分布在磁盘中,每次查询磁臂都要遍历磁盘页中的扇区。

顺序IO:所需的数据地址已经有序,磁臂只需要遍历一次磁盘页的所有扇区。

*当查询出现覆盖索引时,不需要再进行MRR优化,因为覆盖索引本身就是有序的。

覆盖索引参考网址:https://blog.youkuaiyun.com/why444216978/article/details/82953165

MRR优化参考网址:https://www.tinymind.net.cn/articles/6cecc9ae6af914

索引的适用场景

1.频繁被查找的字段-----覆盖索引

2.频繁作为查询条件的字段

3.多表关联查询的关联字段

4.需要排序的字段-----order by

5.需要统计或分组的字段-----group by

索引失效的常见场景

1.条件中有or(尽量少用or,改用union)

2.覆盖索引没有按最左匹配原则使用

3.范围条件后面的索引全部失效

4.条件中有不等号

5.字段不能为空的情况下使用is null/is not null

6.Like模糊查询以%开头

7.索引字段运用了计算、函数或类型转换

场景一: 确认1.碰到了一个一个常慢的SQL server语句,发现是变量查询时很慢 SQL语句: DECLARE @SN VARCHAR(12) SET @SN = '30F335CD0045' SELECT [Mac2] FROM SF_Cp_Detail WHERE [Mac2] = @SN 确认2.查看索引是:唯一非聚集索引 CREATE UNIQUE NONCLUSTERED INDEX [IX_SF_CP_Detail_MAC2] ON [dbo].[SF_Cp_Detail] ( [Mac2] ASC ) WHERE ([MAC2]'' AND [MAC2] IS NOT NULL) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO 确认3.执行计划如下: 执行计划 SET STATISTICS IO ON ; (0 行受影响) Table 'SF_Cp_Detail'. Scan count 33, logical reads 1267942, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 场景二: 为什么用不到索引IX_SF_CP_Detail_MAC2]呢? 尝试1: 把唯一非聚集索引改为非聚集索引, Done,用到索引了. Drop index ……. CREATE NONCLUSTERED INDEX [IX_SF_Cp_Detail_Mac2] ON [dbo].[SF_Cp_Detail] ( [Mac2] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO 尝试2: 可是还需要验证唯一性怎么办呢? 试了半天未达到目标, 根据别人提示, 恢复唯一聚集 CREATE UNIQUE NONCLUSTERED INDEX [IX_SF_CP_Detail_MAC2] ON [dbo].[SF_Cp_Detail] ( [Mac2] ASC ) WHERE ([MAC2]'' AND [MAC2] IS NOT NULL) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO 然后 修改查询: DECLARE @SN VARCHAR(12) SET @SN = '30F335CD0045' SELECT [Mac2] FROM SF_Cp_Detail WHERE [Mac2] = @SN option (recompile) 预计查询计划 看样子不行, 但是,看一下实际查询计划: OK ,Done,可以了. 尝试3. 但是我不可能去每个程序加option (recompile)呀, 而且随着数据量的增大,每次重新编译索引, 本身就导致SQL语句变慢. 最终解决方案: 唯一非聚集索引留着, 再添加一个 非聚集索引,保留两个索引, 终于搞定了. CREATE UNIQUE NONCLUSTERED INDEX [IX_SF_CP_Detail_MAC2] ON [dbo].[SF_Cp_Detail] ( [Mac2] ASC ) WHERE ([MAC2]'' AND [MAC2] IS NOT NULL) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE NONCLUSTERED INDEX [IX_SF_Cp_Detail_Mac2] ON [dbo].[SF_Cp_Detail] ( [Mac2] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值