数据库索引
2021/7/17 2:06:02
本文主要是介绍数据库索引,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
文章目录
- 1. 基础概念
- 2. 避免索引失效
- 3. 聚簇索引与辅助索引
- 4. 覆盖索引
- 5. 最左前缀原则
- 6. 冗余索引
1. 基础概念
索引概念:
- 它是帮助mysql高效获取数据的数据结构;
- 索引以某种方式指向数据,通过索引可以快速获取数据;
- 没有索引时,查找,只能遍历,O(N)的时间复杂度 (避免全表扫描);
- 建立了索引,查找速度就显著提高,一般是B+树索引,且索引像目录,可提高查询效率;
- 通过索引对数据进行排序,降低排序成本;
索引劣势:
- 索引本身是一张表,保存了主键与索引字段,并指向实体类的记录,所以其也要存储空间,一般放到磁盘
- 插入数据时也要更新索引,从而影响写入数据的效率
索引结构:
- 不同的存储引擎,它的索引是不一样的
- BTREE索引是最常见的,也是InnoDB引擎所支持的索引
hash索引缺点:
- hash不能够进行范围查找;
- hash键值对的形式使得其键只能用一个,导致只能主键查询,不能用其它字段建立索引查询;
- hash冲突(不论邻接法还是开链法)都有一定线性时间的查找,不一定比B+树索引快;
对于B树和B+树的相关内容见:B树、B+树详解。
索引分类:
- 单值索引:(单列索引)按照单列,一个表可以有多个;
- 唯一索引:索引值必须唯一,允许有空值;
- 复合索引:多个列一起构成索引;
索引语法:
- 可以在创建表时创建,也可以之后创建
- mysql中主键有默认的索引 PRIMARY
- 索引类型默认是BTREE
- 可以create,也可以alter
索引的设计原则:
- 对于查询频次高,且数据量比较大的表
- 针对 经常在where子句中出现的字段
- 尽量使用唯一索引,区分度高,索引效率高
- 并不是多多益善,在insert,update和delete也要维护
- 使用短字段的索引,节省空间
- 针对复合(联合)索引,创建一个组合索引,其所有子集(从左边连续),都有索引(最左前缀);
索引是越多越好吗:
- 数据量小的表不需要索引,建立会增加额外的开销
- 数据变更需要维护索引,因此需要更多的维护成本
- 索引本身需要空间
2. 避免索引失效
- ①全值匹配,对索引中所有列都指定具体值(该情况下,索引生效,执行效率高);
- ②最左前缀法则,如果索引了多列,要遵守最左前缀法则。即查询从索引的最左前列开始(从最左前列开始,不管其相对位置),且不跳过索引中的列(若是跳过,查询时从跳过处截断);
- ③范围查询右边的列,不能够使用索引,即范围查询右边的查询条件失效;
- ④不要在索引列上进行运算操作,索引将失效;
- ⑤字符串不加单引号,造成索引失效;
- ⑥尽量使用覆盖索引(只访问索引的查询(索引列完全包含查询列)),减少
select *
;
explain中的Extra字段含义:
(1)using index:使用覆盖索引的时候出现;
(2)using where:在查找使用索引的情况下,需要回表去查询所需数据;
(3)using index condition:查找使用了索引,但是需要回表查询数据;
(4)using index; using where:查找使用了索引,但是需要的数据都在索引中能找到,所以不需要回表查询数据; - ⑦用
or
分隔开的条件,如果or
前的条件中的列有索引,而后边的列中没有索引,那么涉及的索引都不会被用到; - ⑧以%开头的like模糊查询,索引失效,如果仅仅是尾部模糊匹配,索引不会失效。如果是头部模糊匹配,索引失效。解决办法是使用覆盖索引来搭配前部模糊查询条件;
- ⑨如果Mysql评估使用索引比全表慢,则不使用索引;
(1)is NULL,is NOT NULL有时索引失效,原因是索引内的数据的成分; - ⑩in 走索引,not in 索引失效;
- ⑾单列索引和复合索引,尽量使用复合索引(相当于创建了索引列个数的索引)而非单列索引(此时数据库会选择一个最优的索引,辨识度最高的来使用,并不会使用全部索引);
3. 聚簇索引与辅助索引
- 聚簇索引的叶子节点包含全部的数据信息,即除了该索引字段的话也有剩余其他所有字段的数据;
- 辅助索引中叶子节点可能只有指向行数据的指针,or 主键;
- 在InnoDb和MyISAm中,是不一样的,可以看下面图;
- ;
- 左边的需要两次查询,这是一个回表;
- 对于InnoDB,其必有聚簇索引;
- ;
4. 覆盖索引
-
只需要在一棵索引树上就能获取SQL所需的所有列数据,无需回表,速度更快。
-
就是索引本身就已经包含了 所要查询的列。
-
则此时就不用进行回表,直接返回就好
-
哈希索引、空间索引等索引都把存储索引列的值,所以mysql只能使用B-TREE来做覆盖索引
-
这里Extra,如果using index,就是覆盖索引(见上文)
- using where 回表查询
- using index 覆盖索引
- using index condition 部分条件不能索引, 所以先用能索引的先走一遍, 然后再使用不能用索引的条件
- 如果type是ALL,则是全表查询
-
主键是不需要加入聚集索引的,因为它本身就在索引的data中
-
这也引出一个问题,非聚集索引不一定回表(如果是覆盖索引,或者是主键)
-
MySQL 的覆盖索引与回表 - 知乎 (zhihu.com)这个写的不错, 忘记了看这个
-
什么时候发生覆盖索引
- 比如where 非主键字段, select 主键, 非主键字段, 此时, 本身非主键字段就在索引树上, 其次非聚集索引叶子存储的是主键, 所以一颗索引树就覆盖了查询的结果
- 比如where 非主键字段 命中了联合索引的左边, 那么select 联合索引中的字段, 就会发生覆盖索引
-
什么时候需要用覆盖索引
- 全表count查询, 建立count(字段), 该字段的索引, 可以直接通过索引得到结果, 不然要回表
- select 多个字段, 可以考虑建立联合索引来覆盖
5. 最左前缀原则
对于联合索引,如果查询的时候查询条件精确匹配索引的左边连续一列或几列,则此列就可以被用到。
这里需要注意的是,查询的时候如果两个条件都用上了,但是顺序不同,那么现在的查询引擎会自动优化为匹配联合索引的顺序,这样是能够命中索引的。
如果遇到范围查询时,就停止匹配了
最左匹配的成因:mysql按照联合索引的顺序,以第一个字段排序,然后再这个基础上再按第二个字段排序,所以对于第二个字段,实际它是局部有序,整体无序的,所以不能跳过第一个字段,直接从第二个字段开始进行,所以最左匹配原则
举个例子:
如User表的name和city加联合索引就是(name,city)
select * from user where name=xx and city=xx ; //可以命中索引 select * from user where name=xx ; // 可以命中索引 select * from user where city=xx ; // 无法命中索引
6. 冗余索引
- 如(name,city )和(name )这两个索引就是冗余索引,能够命中后者的查询肯定是能够命中前者的
这篇关于数据库索引的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-02Java微服务系统项目实战入门教程
- 2024-11-02Java微服务项目实战:新手入门指南
- 2024-11-02Java项目实战:新手入门教程
- 2024-11-02Java小程序项目实战:从入门到简单应用
- 2024-11-02Java支付系统项目实战入门教程
- 2024-11-02SpringCloud Alibaba项目实战:新手入门教程
- 2024-11-02Swagger项目实战:新手入门教程
- 2024-11-02UNI-APP项目实战:新手入门与初级教程
- 2024-11-02编译部署资料入门教程:一步步学会编译和部署
- 2024-11-02地图服务资料入门指南