type
status
date
slug
summary
tags
category
icon
password
MyISAMInnoDB索引结构B+Tree 索引结构hash 索引结构索引分类:索引的存储形式通过索引查询的执行过程SQL 性能分析SQL执行频率慢查询日志explain 执行计划Explain 执行计划中各个字段的含义:索引使用(失效)最左前缀法则范围查询索引列运算字符串不加引号 模糊查询or连接条件(只要一边没有索引就会失效)数据分布影响SQL提示覆盖索引
MyISAM
InnoDB
索引结构
B+Tree 索引结构

hash 索引结构
思考:为什么InnoDB存储引擎选择使用B+tree索引结构?

索引分类:

索引的存储形式
而在在InnoDB存储引擎中,根据索引的存储形式,又可以分为以下两种:聚集索引、二级索引

聚集索引的结构就是一个B+Tree,他的叶子节点挂的就是一行数据,比如主键id为5,叶子节点为5,那么叶子节点下的数据就为id的为5的这行数据
二级索引的结构也是一个B+Tree,二级索引的叶子节点存储的是当前值所在行的id,如name是一个二级索引,值为:“张三”,当前id为 3,那么叶子节点存储的值就是3。

通过索引查询的执行过程

SQL 性能分析
SQL执行频率
MySQL 客户端连接成功后,通过 show [session|global] status 命令可以提供服务器状态信 息。通过如下指令,可以查看当前数据库的INSERT、UPDATE、DELETE、SELECT的访问频次:

通过查询SQL的执行频次,我们就能够知道当前数据库到底是增删改为主,还是查询为主。 那假 如说是以查询为主,我们又该如何定位针对于那些查询语句进行优化呢? 我们可以借助于慢查询日志。
慢查询日志
Linux 开启慢查询日志方式:


检查慢查询日志 :可以清楚的看到某段时间当中那些sql语执行效率低

show profiles 能够在做SQL优化时帮助我们了解时间都耗费到哪里去了。通过have_profiling 参数,能够看到当前MySQL是否支持profile操作:

explain 执行计划
EXPLAIN 或者 DESC命令获取 MySQL 如何执行 SELECT 语句的信息,包括在 SELECT 语句执行 过程中表如何连接和连接的顺序。
语法:
Explain 执行计划中各个字段的含义:


索引使用(失效)
最左前缀法则
查询条件必须包含最左边的列,不包含最左边的列将导致索引全部失效,跳过中间的列会导致部分索引失效(如果跳过中间列,中间列后面字段索引失效)。

示例:

这里可以计算出 status 字段索引长度为 5 (54 - 49 = 5)

这里可以得出 age 索引长度为 2,profession 索引长度为 47

未使用最左边的条件导致索引失效

联合索引跳过中间字段导致部分索引失效

最左前缀法则与条件顺序无关,条件包含最左边的列即可

注意 : 最左前缀法则中指的最左边的列,是指在查询时,联合索引的最左边的字段(即是 第一个字段)必须存在,与我们编写SQL时,条件编写的先后顺序无关。(联合索引被跳过的字段后面字段的都会失效)
范围查询
联合索引中,出现范围查询(>,<),范围查询右侧的列索引失效。
当范围查询使用> 或 < 时,走联合索引了,但是索引的长度为49,就说明范围查询右边的status字 段是没有走索引的。

解决方案:在业务允许的情况下,尽可能的使用类似于 >= 或 <= 这类的范围查询,而避免使用 > 或 <
当范围查询使用>= 或 <= 时,走联合索引了,但是索引的长度为54,就说明所有的字段都是走索引的。

索引列运算
不要在索引列上进行运算操作, 索引将失效。
当根据phone字段进行函数运算操作之后,索引失效。

字符串不加引号
字符串类型字段使用时,不加引号,索引将失效。
如果字符串不加单引号,对于查询结果,没什么影响,但是数 据库存在隐式类型转换,索引将失效。

模糊查询
如果仅仅是尾部模糊匹配,索引不会失效。如果是头部模糊匹配,索引失效。
接下来,我们来看一下这三条SQL语句的执行效果,查看一下其执行计划: 由于下面查询语句中,都是根据profession字段查询,符合最左前缀法则,联合索引是可以生效的, 我们主要看一下,模糊查询时,%加在关键字之前,和加在关键字之后的影响。

or连接条件(只要一边没有索引就会失效)
用or分割开的条件, 如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到
由于age没有索引,所以即使id、phone有索引,索引也会失效。所以需要针对于age也要建立索引。

然后,我们可以对age字段建立索引。
建立了索引之后,我们再次执行上述的SQL语句,看看前后执行计划的变化。

最终,我们发现,当or连接的条件,左右两侧字段都有索引时,索引才会生效。
数据分布影响
如果绝大部分数据都满足查询条件则会走全表扫描,如果绝大部分数据都不满足查询条件则会走索引。

就是因为MySQL在查询时,会评估使用索引的效率与走全表扫描的效率,如果走全表扫描更快,则放弃 索引,走全表扫描。 因为索引是用来索引少量数据的,如果通过索引查询返回大批量的数据,则还不 如走全表扫描来的快,此时索引就会失效。
SQL提示
SQL提示,是优化数据库的一个重要手段,简单来说,就是在SQL语句中加入一些人为的提示来达到优 化操作的目的。(给MySQL一个提示,用那个一个索引)
1). use index : 建议MySQL使用哪一个索引完成此次查询(仅仅是建议,mysql内部还会再次进行评估)。
2). ignore index : 忽略指定的索引。
3). force index : 强制使用索引。
覆盖索引
尽量使用覆盖索引,减少select *。 那么什么是覆盖索引呢? 覆盖索引是指 查询使用了索引,并且需要返回的列,在该索引中已经全部能够找到 。

示例:


使用主键 ID 查询之所以可以提高效率,是因为只需要遍历一次聚集索引,聚集索引的叶子节点记录了一整行的数据,直接返回即可。

覆盖索引:
查询需要返回的字段在当前的索引结构当中都已经找到了,这种就叫覆盖索引,不需要再进行回表,一次索引扫描就完成了。

回表 查询:
此处就是一个回表查询示例,首先会去扫描辅助索引,在辅助索引中拿到id,再去扫描聚集索引找到对应的id,
然后再从此id叶子节点下挂载的行数据中提取出需要返回的字段,如此实例中的 gender 字段
