MySQL索引实现、MySQL索引原理、索引下推、索引覆盖、索引失效
作者:互联网
文章目录
索引实现
https://www.cnblogs.com/jiawen010/p/11805241.html
目前MySQL的Innodb、Myisam存储引擎都是使用的B+树作为存储结构;
但是 memory存储引擎 确是 hash索引,所以索引数据结构要 结合 具体的存储引擎;
InnoDB索引实现
注意:一个索引节点就表示一个磁盘页
InnoDB的主键索引
InnoDB的聚簇索引 的 data域 存的是 行数据(具体数据);
非叶子节点存的是 索引,叶子节点存的是数据;
InnoDB的辅助索引
InnoDB的所有辅助索引 的 data域 存的是 主键;
辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。
MyISAM索引实现
MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址;
在MyISAM中,主键索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复;
Innodb索引和MyISAM索引的区别
- Innodb 主键使用的是聚簇索引,MyISam主键索引使用的是非聚簇索引;
- Innodb主键索引的叶子节点存放的是行记录,是具体的数据,Innodb非聚簇索引 叶子节点(data域)存放的是主键;而MyISam的聚簇索引和非聚簇索引都存放的是行数据的具体地址;
其它索引数据结构
hash索引的缺点
缺点: 因为底层数据结构是散列的,无法进行比较大小,不能进行范围查找
B+树和二叉查找树的性能对比
B树包括B+树的设计思想都是尽可能的降低树的高度,以此降低磁盘IO的次数,因为一个索引节点就表示一个磁盘页。
一个索引节点就表示一个磁盘页;
假设一个节点可以容纳100个值,那么3层的B+树可以容纳100万个数据。
根节点100,第二层100*100,第三次存数据就是100x100x100,z三层只需3次io;
而如果使用二叉查找树,则需要将近20层,也就是进行20次磁盘IO;
B+对比B树的优点
B树的每个节点除了存储指向子节点的索引之外,还有data域,因此单一节点存储的指向子节点的索引并不是很多,树高度较高,磁盘IO次数较多,
个人理解,B树的索引节点,既存索引也存数据,一次io读取的数据是有限的,所以b树存的索引相对于b+树少,在数据量大的情况下,b树io次数多;
假设 一个索引可以存100单位数据,索引和data分别需要1单位,那么3层b树能存50+50x50+50x50*50个索引,而3层b+树可以存100x100x100,故b+树可以存更多索引;
总结:b+树的节点可以存更多索引数据,而b树的节点既要存索引,又要存数据,因此存的索引少;
其它关于索引数据结构的问题
为什么数据库索引不用红黑树而用B+树
红黑树在插入删除操作时需要 通过旋转和变色操作 来恢复二叉树性质;
但是当数据量较小,数据完全可以放入内存中,不需要进行磁盘IO,这时候,红黑树时间复杂度比B+树低。
索引失效
https://www.cnblogs.com/wdss/p/11186411.html
条件中or前后没有同时使用索引,索引失效
例如select * from user where name="zhsngsan" or id=29527;
其中id是主键,那么id是主键索引,而name不是索引,则索引失效;
like 以%开头,索引失效
当like前缀没有%,后缀有%时,索引有效。
组合索引,不是使用第一列索引,索引失效
https://zhuanlan.zhihu.com/p/108179618
例如 create index test2 on emp(ename , empno,job);
,其中ename就是第一列索引,只要条件中不含ename组合索引就会失效;
数据类型出现隐式转化,索引失效
如varchar不加单引号的话可能会自动转换为int型,使索引无效;
其它情况
不推荐使用索引的情况
- 数据唯一性差(一个字段的取值只有几种时)的字段不要使用索引
比如性别,只有两种可能数据。意味着索引的二叉树级别少,多是平级。这样的二叉树查找无异于全表扫描。
- 频繁更新的字段不要使用索引
比如logincount登录次数,频繁变化导致索引也频繁变化,增大数据库工作量,降低效率。
- 字段不在where语句出现时不要添加索引,如果where后含IS NULL /IS NOT NULL/ like ‘%输入符%’等条件,不建议使用索引
只有在where语句出现,mysql才会去使用索引
4) where 子句里对索引列使用不等于(<>),使用索引效果一般
覆盖索引
只需要在一棵索引树上就能获取SQL所需的所有列数据的索引成为覆盖索引(Covering Index),无需回表,速度更快。
//id是主键、name是索引,则下面sql需要回表,因为需要通过id回表获取sex;
select id,name,sex from user where name='shenjian';
但是,如果再创建一个联合索引(name,sex),那么上面的sql就不需要回表;因为通过(name,sex)的索引可以获取id,name,sex 不需要回表;
组合索引
最左匹配原则
https://chensj.blog.csdn.net/article/details/108540362
组合索引abc_index:(a,b,c),只会在where条件中带有(a)、(a,b)、(a,b,c)的三种类型的查询中使用使用索引。
当where条件只有(a,c)时也会走,但是只走a字段索引,不会走c字段。
注意
- 当遇到范围查询(>、<、between、like)就会停止匹配。
(a,b,c,d)建立索引,
where后条件为a = 1 and b = 2 and c > 3 and d = 4
那么,a,b,c三个字段能用到索引,而d就匹配不到。因为遇到了范围查询!
组合索引数据结构
联合索引中的索引项会先根据第一个索引列进行排序,第一个索引列相同的情况下,会再按照第二个索引列进行排序,依次类推。
例如联合索引abc_index:(a,b,c),sql where a=1and b=2 and c=3;
先根据a查询,a相同的情况下,b是排好序的,因此可以定位到b,同理c;
但是如果sql是where a=1,c=3;a会走索引得出主键,再根据主键回表查c;
因为a相同时,c是乱序的;
总结
联合索引(a,b,c)可以直接定位到a,ab,abc,至于ac需要2次定位;
索引下推
https://blog.csdn.net/luxiaoruo/article/details/106637231
https://blog.csdn.net/qq_34162294/article/details/105260154
在不使用索引下推的情况下,使用非主键索引进行查询时,存储引擎 通过索引检索到数据,然后返回给MySQL服务器,服务器做最后的筛选。
例如查询gander=男 and age>20
的数据,
不使用索引下推时,存储引擎将gander=男
的数据直接返回 给mysql服务层,再由 服务层 根据age>20
筛选出最终数据返回Clint;
使用索引下推后,存储引擎 直接筛选gander=男 and age>20
的数据返回 给mysql服务层;
谓词下推
什么是谓词
谓词下推概念中的谓词指返回bool值即true和false的函数,或是隐式转换为bool的函数:
SQL中的谓词主要有 LKIE、BETWEEN、IS NULL、IS NOT NULL、IN、EXISTS。
谓词下推
https://blog.csdn.net/EdwardWong_/article/details/105970779
谓词下推 Predicate Pushdown:基本策略是,始终将过滤表达式尽可能移至靠近数据源的位置。
简而言之,就是在不影响结果的情况下,尽量将过滤条件提前执行。
- 例如
select count(1) from A Join B on A.id = B.id where A.a > 10 and B.b < 100;
在处理Join操作之前需要首先对A和B执行TableScan操作,然后再进行Join,再执行过滤,最后计算聚合函数返回,但是如果把过滤条件A.a > 10和B.b < 100分别移到A表的TableScan和B表的TableScan的时候执行,可以大大降低Join操作的输入数据。优化后的语句如下:
select count(1) from (select * from A where a>10)A1 Join (select * from B where b<100)B1 on A1.id = B1.id;
标签:下推,节点,索引,MySQL,失效,where,主键 来源: https://blog.csdn.net/qq_43369986/article/details/116747163