MYSQL---查询优化的基本思路和原则

一、常用优化的原则

  • 永远用小结果集驱动大结果集
  • 尽可能在索引中完成排序
  • 只取出自己需要的列
  • 仅仅使用最有效的过滤条件
  • 尽可能避免复杂的join和子查询
  • 多使用profile

1. 在这里需要严格的说是小结果集驱动大结果集,而不能用人们通常所说的小表驱动大表。因为在where条件过滤后大表数据未必就比小表多,反而适得其反。因为在mysql的join中是通过嵌套循环来实现的,驱动结果集越大,所需要循环的次数就越多。跟就会导致被驱动表的访问次数增多,即使需要的IO很少但是次数多了总量影响也不可能很小更会导致CPU运算量跟着增加。所以在优化Join SQL时最基本的原则就是小结果集驱动大结果集。通过这个原则减少循环次数,从而减少IO和CPU的开销。

二、优化思路

  • 优化更需要优化的SQL
  • 定位优化对象的性能瓶颈
  • 明确的优化目标
  • 从explain入手

1. 什么是优化更需要优化的SQL,比如当前两个SQL1与SQL2。假设SQL1每小时执行1000次,每次IO消耗性能为10。SQL2每小时执行10次每次性能消耗1000。总的来看相同时间内它两所损耗的IO性能是一样的。但是我们只需要让IO减少一小块资源消耗就可以让CPU节省出一大块资源,尤其是对排序、分组这些CPU消耗巨大的操作中。从系统层面来说一个高并发的SQL危险性也远比,一个低并发的SQL危险性大得多。如果从两者之间取舍的话我们应更倾向于,当然能都进行优化是更好的。
2. 在拿到一条需要优化的SQL时首先需要定位,这条SQL的问题在哪为什么要优化它。而不是为了优化而优化,从而开始一个又一个的优化方法开始尝试。首先要判断这个SQL瓶颈到底是在IO还是CPU。到底是在数据访问花费很多时间还是在数据运算。大多数情况可以通过profiling找到瓶颈所在。
3. 在定位到了性能瓶颈之后,就需要通过分析该SQL所完成的功能和对系统的整体影响制定出一个明确的优化目标。
4. 具体从explain入手分析SQL在数据库中具体以一个怎样的执行计划来实现的。人是活的具体怎么分析怎么执行还是根据当前情况等因素定的。这里只是一个普通的思路。实际优化过程中就要根据经验等因地制宜的实施了。

三、explain使用

1.各种信息解释:

id: 查询优化器所选定的执行计划中查询的序列号

select_type:

  • simple :即简单select 查询,不包含union及子查询
  • primary :子查询中最外层的 select 查询,注意并不是逐渐查询
  • union :表示此查询是 union 的第二或随后的查询
  • dependent union:union 中的第二个或后面的查询语句, 取决于外面的查询
  • union result :子查询中的union的,且为union中从第二个select开始的后面所有select,同样依赖于外部查询的结果集
  • subquery :子查询中内层的第一个select,依赖于外部查询的结果集
  • dependent subquery:子查询中的第一个select,取决于外面的查询,即子查询依赖于外层查询的结果
  • uncacheable subquery:结果集无法缓存的子查询,必须重新评估外链接的第一行
  • derived: 在from列表中包含的子查询被标记为derived,mysql会递归这些子查询,把结果放在临时表里

table: 显示这一步访问的数据库中的表名称

Type: 性能从好到坏依次如下

  • system:表中只有一条数据,这是一个特殊的const 类型;
  • const:针对主键或唯一索引的等值查询扫描,最多只返回一行数据,const 查询速度非常快,因为它仅仅读取一次即可;
  • eq_ref:此类型通常出现在多表的 join 查询,表示对于前表的每一个结果,都只能匹配到后表的一行结果,并且查询的比较操作通常是=, 查询效率较高;
  • ref:此类型通常出现在多表的 join 查询, 针对于非唯一或非主键索引, 或者是使用了 最左前缀 规则索引的查询;
  • fulltext:全文索引检索,要注意,全文索引的优先级很高,若全文索引和普通索引同时存在时,mysql不管代价,优先选择使用全文索引;
  • ref_or_null:与ref方法类似,只是增加了null值的比较。实际用的不多;
  • unique_subquery:用于where中的in形式子查询,子查询返回不重复值唯一值;
  • index_subquery:用于in形式子查询使用到了辅助索引或者in常数列表,子查询可能返回重复值,可以使用索引将子查询去重;
  • index_merge:表示查询使用了两个以上的索引,最后取交集或者并集,常见and,or的条件使用了不同的索引,官方排序这个在ref_or_null之后,但是实际上由于要读取所个索引,性能可能大部分时间都不如range;
  • range:表示使用索引范围查询,通过索引字段范围获取表中部分数据记录。这个类型通常出现在 =, <>, >, >=, <, <=, IS NULL, <=>, - BETWEEN, IN操作中,此时输出的 ref 字段为 NULL并且key_len字段是此次查询中使用到的索引的最长的那个;
  • index:全表扫描,只是扫描表的时候按照索引次序进行而不是行。主要优点就是避免了排序,但是开销仍然非常大,这种情况时, Extra 字段会显示 Using index;
  • all:性能最差的情况,使用了全表扫描,系统必须避免出现这种情况。
    阿里建议:
    在这里插入图片描述

possible_keys: 该查询可以利用的索引,如果没有任何索引可以使用就会显示成null。这一项内容对优化时索引的调整十分重要。

key: 从possible_keys中选择真正用到的索引

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

ref: 表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值

rows: 表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数

Extra: 查询中每一步实现的额外信息

  • Using where:列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表的全部的请求列都是同一个索引的部分的时候,表示mysql服务器将在存储引擎检索行后再进行过滤
  • Using temporary:表示MySQL需要使用临时表来存储结果集,常见于排序和分组查询
  • Using filesort:MySQL中无法利用索引完成的排序操作称为“文件排序”
  • Using join buffer:改值强调了在获取连接条件时没有使用索引,并且需要连接缓冲区来存储中间结果。如果出现了这个值,那应该注意,根据查询的具体情况可能需要添加索引来改进能。
  • Impossible where:这个值强调了where语句会导致没有符合条件的行。
  • Select tables optimized away:这个值意味着仅通过使用索引,优化器可能仅从聚合函数结果中返回一行
  • Distinct:优化distinct操作,在找到第一匹配的元组后即停止找同样值的动作
  • Using filesort:说明mysql会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取,mysql中无法利用索引完成的排序操作称为"文件排序"

四、profile使用

分析SQL执行带来的开销是优化SQL的重要手段。在MySQL数据库中,可以通过配置profiling参数来启用SQL剖析。该参数可以在全局和session级别来设置。对于全局级别则作用于整个MySQL实例,而session级别紧影响当前session。该参数开启后,后续执行的SQL语句都将记录其资源开销,诸如IO,上下文切换,CPU,Memory等等。根据这些开销进一步分析当前SQL瓶颈从而进行优化与调整。在我们常使用的一些工具如,Navicat,SQLyog都有直接的返回信息。都能直观的帮我们展示相关信息。
在这里插入图片描述
在这里插入图片描述
如果没有打开,则需要set profiling=1;手动设置开启
并且默认是不显示CPU,Block等信息的这都需要我们手动输入显示。show profiles;找到对应query_id再按照id进行自定义查询你想得到的信息即可。

type: 
 ALL --显示所有的开销信息 
 | BLOCK IO --显示块IO相关开销 
 | CONTEXT SWITCHES --上下文切换相关开销 
 | CPU --显示CPU相关开销信息 
 | IPC --显示发送和接收相关开销信息 
 | MEMORY --显示内存相关开销信息 
 | PAGE FAULTS --显示页面错误相关开销信息 
 | SOURCE --显示和Source_function,Source_file,Source_line相关的开销信息 
 | SWAPS --显示交换次数相关开销的信息 

例如:
SHOW PROFILE BLOCK IO, CPU for query 131;
在这里插入图片描述
剩余的就实践中慢慢探索吧

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值