【Mysql】调优必知的sql访问方式

mysql的访问方法概念

mysql在执行我们的sql语句的时候,会经过查询优化器将我们的sql语句进行优化,然后采用最小的查询成本来执行我们的sql。
mysql可以采用的查询方式有以下几种

  • 采用全表扫描的方式来进行查询
  • 使用索引进行查询
    • 使用主键索引或者唯一二级索引进行等值查询
    • 使用普通二级索引进行等值查询
    • 针对索引列进行范围查询
    • 遍历整个索引进行查询
      mysql在执行查询语句的时候,可能会采用多种查询方式进行查询,当然mysql会计算多种查询方式查询成本,采用最优的方式来进行查询

建立索引
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QI6OQkIS-1664257518447)(evernotecid://3FF987EF-EC0D-4AE0-B527-B88DFA6E477C/appyinxiangcom/26972899/ENResource/p318)]

常见的几种访问方式

system

表只有一行记录(等于系统表),这是const类型的特列,平时不会出现,这个也可以忽略不计

const

const 意思是常数级别的,代价是可以忽略不计的。不过这种const访问方法只能在主键列或者唯一二级索引列和一个常数进行等值比较时才有效,如果主键或者唯一二级索引是由多个列构成的话,索引中的每一个列都需要与常数进行等值比较,这个const访问方法才有效(这是因为只有该索引中全部列都采用等值比较才可以定位唯一的一条记录)

# key2为唯一索引
SELECT * FROM single_table WHERE key2 = 3841;
# 查询null
SELECT * FROM single_table WHERE key2 IS NULL;
ref

ref的查询方法大致的步骤是,针对于普通二级索引,先通过普通二级索引定位到符合条件的二级索引的对应的主键ID,然后在通过主键ID去聚簇索引中查询对应的数据。
ref的查询方法和const的区别是,通过二级索引查询时,可能会查询到多个符合条件的二级索引的值,然后在分别回表查询。当查询到的数据比较多时,回表查询的代价也是比较大的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GUv6dPUX-1664257518448)(evernotecid://3FF987EF-EC0D-4AE0-B527-B88DFA6E477C/appyinxiangcom/26972899/ENResource/p316)]

二级索引列值为null的情况

不论是普通的二级索引,还是唯一二级索引,它们的索引列对包含NULL值的数量并不限制,所以我们采用key IS NULL这种形式的搜索条件最多只能使用ref的访问方法,而不是const的访问方法。

对于联合索引这种二级索引来说,只要最左边的连续索引列与常数进行比较,就有可能使用到ref的访问方法,类似于我们常讲的最左匹配原则

ref_or_null

ref_or_null这种访问方法适用于我们不仅想找出某个二级索引列的值等于某个常数的记录,还想把该列的值为null的记录一起查出来,当使用二级索引进行查询而不是全表扫描的时候,这种访问方法就是ref_or_null

SELECT * FROM single_table WHERE key1 = 'abc' OR key1 IS NULL;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UmifFsz5-1664257518448)(evernotecid://3FF987EF-EC0D-4AE0-B527-B88DFA6E477C/appyinxiangcom/26972899/ENResource/p317)]

range

上面几种访问方式都是索引列与某一个常数值进行等值比较时的访问方法。如果我们的查询是针对于索引进行范围查询的话,我们除了可以采用回表查询的方式,也有可能会用到二级索引+回表的查询方式进行查询。


SELECT * FROM single_table WHERE key2 IN (1438, 6328) OR (key2 >= 38 AND key2 <= 79);

上面这个查询,就涉及到了索引的范围查询。
所以,range这种访问方式,就是值利用索引进行了范围匹配。
索引可以是聚簇索引也可以是二级索引

index
SELECT key_part1, key_part2, key_part3 FROM single_table WHERE key_part2 = 'abc';

分析下上面的这个查询语句,查询的三个字段我们已经建立的联合索引,但是where的条件中只有联合索引中间的 key_part2,我们知道针对于联合索引的等值查询,如果符合最左匹配原则的话,那么是可以采用ref的访问方式的。但是目前的where条件不符合最左原则,所以不能采用ref的访问方式。
因为我们对所要查询的字段key_part1,key_part2,key_part3建立了二级索引,所以尽管不符合最左原则,但是我们可以直接通过遍历二级索引,然后在二级索引中找出符合查询条件的记录,这样也不需要回表查询,直接通过遍历二级索引的方式就能查询到我们想要的数据。这种访问方式叫做index
采用index的这种访问方式,虽然我们遍历了二级索引,但是二级索引比聚簇索引要小的多。

all

all这种访问方式通过名字我们也能看出来,这种就是全表扫描的查询方式了。

查看sql的访问方法

我们可以通过查看sql的执行计划来查看sql的具体采用了那种访问方式

# 在udc_company表中,ID为主键索引
EXPLAIN SELECT * FROM udc_company WHERE ID='2b6e4413-e29e-5fd9-82b8-13694634f9c6'

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ltRZugiA-1664257518448)(evernotecid://3FF987EF-EC0D-4AE0-B527-B88DFA6E477C/appyinxiangcom/26972899/ENResource/p320)]

我们通过查看查询计划,可以看到对于主键索引的等值查询,查询的type就是const

EXPLAIN执行计划结果解析

通过explain我们可以获得以下信息:

  • 表的读取顺序
  • 数据读取操作的操作类型
  • 哪些索引可以使用
  • 哪些索引被实际使用
  • 表之间的引用
  • 每张表有多少行被优化器查询

下面就来逐个认识一下

id

select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序

例如下面这个sql

EXPLAIN SELECT * FROM reconc_proforma_line WHERE proforma_id =(SELECT ID FROM reconc_proforma WHERE id='000b3d8a-c071-40d1-a575-83a60ec2522c')

当ID相同时,对于多个sql语句的查询会从上到下的顺序依次执行
当sql中有自查询的时候,ID的数字就可能会有不同,此时id 数字越高,查询的优先级越高

  • 多个ID相同的情况说明
EXPLAIN SELECT rp.*,rpl.* FROM reconc_proforma rp,reconc_proforma_line rpl WHERE rp.id='000b3d8a-c071-40d1-a575-83a60ec2522c' and rpl.id='57530f19-8f82-4067-bda8-14d984d51c31'

看下结果
在这里插入图片描述

结果中ID都为1,所以执行顺序从上到下

select_type

select_type主要用来区别普通查询、联合查询和子查询等复杂查询的情况
其主要包含以下几个值:

  • SIMPLE 简单的select查询,查询中不包含子查询或者UNION
  • PRIMARY 查询中若包含任何复杂的子部分,最外层查询则被标记为PRIMARY
  • SUBQUERY 在SELECT或WHERE列表中包含了子查询
  • DERIVED 在FROM列表中包含的子查询被标记为DERIVED(衍生),MySQL会递归执行这些子查询,把结果放在临时表中
  • UNION 若第二个SELECT出现在UNION之后,则被标记为UNION:若UNION包含在FROM子句的子查询中,外层SELECT将被标记为:DERIVED
  • UNION RESULT 从UNION表获取结果的SELECT
table

table就比较简单了,指的就是当前的记录所查询的表

partitions

如果查询是基于分区表的话,会显示查询将访问的分区。

type

type就是展示当前sql采用哪种访问类型进行访问查询。常见的类型有:system const ref ref_or_null range index all

possible_keys

possible_keys 显示可能应用在这张表中的索引,一个或多个。查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用。

key

实际上使用到的索引,如果key的值为null,则代表没有使用索引或者没有建立索引

key_len

表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度,在不损失精确性的情况下,长度越短越好。key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的。

ref

这一列显示了在key列记录的索引中,表查找值所用到的列或常量,常见的有:const(常量),字段名等。一般是查询条件或关联条件中等号右边的值,如果是常量那么ref列是const,非常量的话ref列就是字段名。

rows

根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数,也就是说,用的越少越好

filtered

这一列是MySQL 5.1里新加的,它显示的是针对表里符合某个条件(where子句或联结条件)的记录数所做的一个悲观估算的百分比

extra

这一列展示一些额外的信息

下面介绍一下我们常见的几种情况

  • Using index:使用覆盖索引,结果集的字段是索引,如果同时出现了Using Where表明索引用来查找健值,如果没有出现Using Where则表示索引用来直接读取数据,而不是查找键值
  • Using index condition:查询的列不完全被索引覆盖
  • Using where: 查询的列未被索引覆盖,使用了where条件过滤

学习了这些,能帮助我们对sql进行优化。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LLLDa_&

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值