第七篇:MySQL之索引

索引的基本思想

我们都知道算法设计里面有一个非常经典的思想:用空间复杂度来换取时间复杂度的下降!索引就是用额外的空间来增加数据库的查询效率。

索引的类别

1、HASH
按照hash表的方式来组织数据,通过拉链来解决hash冲突。
优点:查询快,插入和删除效率高
缺点:只适合于等值查询,区间查询效率低下
hash索引
2、B+树

MySQL的底层物理结构是page(页),每页中会存放若干条数据行,具体的组织形式可以见第二篇:MySQL之InnoDB物理存储结构

B+树

B+树是一个N叉树,叶子节点存储的为实际的数据,非叶子节点存储的为索引数据。

B树
B树和B+树的格式大概一致,只不过B树的非叶子节点存储的是实际的数据。

B树和B+树的区别:
1、B树的区间查询和排序查询的效率比较低。
2、因为B树的非叶子节点存储的为实际的数据,比B+树只存储主键和页号的数据量要大得多。因此,相比于B+树,B树每个页能够存储的记录数量要少,树也就越高。

InnoDB索引

InnoDB的索引类型主要是B+树。一个索引对应着一颗B+树。

索引的缺点:
索引的好处是查询效率变高,但是为了维护B+树的有序性,插入数据的时候有点麻烦:
1、插入数据的数据页有空闲,这时有可能需要页内之间数据的挪动,效率低下
2、插入数据的数据页已经满了,这个时候需要重新申请一个空白页,然后将数据页中的部分数据挪动过去,这个操作叫做页分裂,此时,数据页的空间利用率也比较低下,时间效率也低下。

索引主要分为以下几种类型

1、主键索引(聚簇索引)
主键上的索引被称为主键索引或者聚集索引、又称为聚簇索引。

主键索引

2、非主键索引(二级索引)

t1二级索引

非主键索引叫做二级索引。
和主键索引不同的是,二级索引中的叶子节点中存储的不是实际的整行数据,而是对应的主键。这样的做法的好处是减少一条数据记录对应的数据大小,使一个叶子节点能够容纳更多数量的数据记录。

二级索引的查询方式:
首先在二级索引中查询出对应的主键,然后在利用主键查询主键索引,这个过程叫做回表

3、联合索引

(t1,t2联合索引)

联合索引就是对两个或者多个列来建立索引,例如对上表中的t1、t2建立联合索引,就是首先对t1进行排序,在t1相同的情况下,按照t2进行排序。
此时,叶子节点存放的是联合索引中对应的数据列+主键

实际操作判断索引使用方式:

explain select XX from XX where xx

在查询语句的开头加入explain关键字后,会返回该查询语句的查询方式,是否走索引,走的哪个索引!

explain关键字

如上图所示,记录了查询的具体信息,我们主要看四个方面:
1、type,查询的方式,从好到坏依次如下所示:
a、system 需要查询的表中只有一条记录或者是空表
b、const 在唯一索引或者主键索引上的等值查询
c、ref 除唯一索引和主键索引外的等值查询
d、range 在所有类别索引上的范围查询
e、index 在所有类别索引上的从头到尾遍历查询
f、all 在主键索引上从头到尾遍历查询

index和all的区别就是 索引上的叶子节点只存储索引对应的列信息,而主键索引对应的叶子节点存放了所有的列信息。因此索引的叶子节点中存放的数据行的数据量小,一个数据页中能够存放更多的数据行。这样的话,如果遍历所有数据行,索引占用的数据页个数要比主键索引更少,查询效率也更高,因为从磁盘上读取数据的成本很高

2、key,使用的索引名字

3、rows 查询时扫描的粗略的行数

4、extra
a、 using index 表示查询的时候直接使用索引上的数据,无需回表
b、 using where 当需要多个条件查询索引时,直接在索引上过滤不符合条件的记录。5.6版本之前还需要将所有记录返回到Server层,在Server层重新过滤。5.6版本之后直接下放到了存储引擎中,这也叫做索引下推
c、 using index condition 和using where 一样,只不过using index condition查询的数据需要重新回表

实践
我们创建了一个num表,id为主键,创建了一个(t1,t2,t3)的联合索引,名字为t1_t2_t3.
num表结构

1、explain select * from num where id = 1;
结果图
主键索引上的等值查询 type为const key 为primary ,也就是主键

2、explain select * from num where id > 1;
结果图
所有索引上的范围查询 包括主键索引 的type为range key为primary

3、explain select * from num where t1 = 10 and t2 > 10;
结果图
extra 为using index condition 表示为索引下推,并且需要回表,因为查询语句为select * ,还需要查询t4 ,因为(t1,t2,t3)联合索引中只有 id,t1,t2,t3的数据。

4、explain select id,t1,t2,t3 from num where t1 = 10 and t2 > 10;
结果图
extra为using index 表示为直接利用联合索引(t1,t2,t3)的索引数据,不需要回表,所以using index condition 变成了using where

5、explain select * from num where t1 = 10;
结果图
type为ref,key为t1_t2_t3,表示这个查询利用了联合索引(t1,t2,t3)

6、explain select * from num where t1 = 1 and t2 = 10
结果图
这个查询语句仍然能利用联合索引。

7、explain select * from num where t2 = 10;

和6相比,7的查询语句无法利用联合索引。

这就叫做最左前缀原则,当利用联合索引的前n个字段进行查询的时候都可以利用联合索引。

8、explain select t1,t2 from num where t2 = 10 and t1 =10
结果图
即使在查询语句中的查询条件顺序不符合联合索引,仍然会走联合索引。因为在MySQL中的优化器中会对查询语句优化,找到最合适的索引执行查询。

9、explain select t1,t2 from num where t1 = 10 and t3 > 10;
在这里插入图片描述
这种情况也会走联合索引,因为t1是有序的,这时会先找到满足t1=10的第一条记录,然后依次往下遍历,直到t1!=10。

10、如果id是字符型,那么前缀匹配用的是索引,中坠和后缀用的是全表扫描。

select * from num where id like ‘A%’;//前缀都是排好序的,使用的都是联合索引
select * from num where id like ‘%A%’;//全表查询
select * from num where id like ‘%A’;//全表查询

11、explain select t1,t2 from num where t2 = 10;
结果图
type为index,直接在联合索引上从头到尾遍历t2,因为t1,t2的数据行存在联合索引(t1,t2,t3)上,遍历联合索引比遍历主键索引效率更高!。联合索引的叶子节点的数据行对应的数据量小,一个数据页能够容纳更多数量的数据行。

12、explain select t1,t2 from num where t4 = 10;
结果图
type为all,因为t4的数据不存在于联合索引(t1,t2,t3)上,所以需要从头到尾遍历主键索引。

13、
在这里插入图片描述

以上两个查询语句,就因为一个t1的大于10,一个t1大于9,却一个type为range,一个type为index。
t1>=9对应的type为index
在这里插入图片描述

t1>=10对应的type为range
在这里插入图片描述

为什么呢?
因为t1>=9的数据行中的t3不是有序的
而t1>=10的数据行中的t3是有序的,我猜测有序的话可以利用二分或者其他更加高效的算法来查询数据,所以type为range

索引小技巧

1、是否选用自增主键?
建议一般情况下选择自增主键。
因为如果主键不自增的话,新记录的主键是随机的,插入的时候还要先查询,并且很容易在一个数据页中间插入记录,需要数据页分裂调整索引,效率低下。
如果主键自增的话,直接在叶子节点的链表的最后一个数据页插入记录就行,并且页分裂的概率不大,效率更高。

2、主键越小越好?
主键越小,二级索引对应的叶子节点中的数据行的数据量越小,叶子节点能够容纳的数据行的数量也就越多,效率更高!

3、是否能够使用业务字段作为主键
不太推荐业务字段作为主键,因为业务字段往往不能保证有序插入,写入数据的成本太高。

4、覆盖索引
对于select t1,t2 from table where t1 = "xx"这个查询语句,如果只有对于t1的索引,在查询t1索引后还需要回表,大大降低了效率,这个时候我们可以将t1索引改为(t1,t2)的联合索引,当走(t1,t2)的联合索引时,会直接返回数据,不需要在回表了,提高了效率。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
【完整课件如下】 MySQL从入门到精通 第01章 初始MySQL(共19页).ppt MySQL从入门到精通 第02章 MySQL的安装与配置(共14页).ppt MySQL从入门到精通 第03章 数据库的基本操作(共11页).ppt MySQL从入门到精通 第04章 数据表的基本操作(共26页).ppt MySQL从入门到精通 第05章 数据类型和运算符(共17页).ppt MySQL从入门到精通 第06章 MySQL函数(共76页).ppt MySQL从入门到精通 第07章 查询数据(共48页).ppt MySQL从入门到精通 第08章 插入、更新与删除数据(共10页).ppt MySQL从入门到精通 第09章 索引(共11页).ppt MySQL从入门到精通 第10章 存储过程和函数(共19页).ppt MySQL从入门到精通 第11章 视图(共20页).ppt MySQL从入门到精通 第12章 触发器(共11页).ppt MySQL从入门到精通 第13章 用户管理(共25页).ppt MySQL从入门到精通 第14章 数据备份与还原(共21页).ppt MySQL从入门到精通 第15章 MySQL日志(共22页).ppt MySQL从入门到精通 第16章 性能优化(共18页).ppt MySQL从入门到精通 第17章 MySQL Workbench5.2 的使用(共15页).ppt MySQL从入门到精通 第18章 MySQL Replication(共27页).ppt MySQL从入门到精通 第19章 MySQL Cluster(共49页).ppt MySQL从入门到精通 第20章 PHP操作MySQL数据库(共7页).ppt MySQL从入门到精通 第21章 MySQL实战-新闻发布系统数据库设计(共6页).ppt MySQL从入门到精通 第22章 MySQL实战-论坛管理系统数据库设计(共6页).ppt

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值