(四)查询性能优化

本文深入探讨了MySQL查询性能低下的原因,并提供了优化查询效率的实用技巧,包括避免不必要的数据加载、使用索引覆盖扫描、重构复杂查询、合理利用查询优化器、排序优化策略、在同一个表上查询和更新的最佳实践、COUNT()优化、用户自定义变量的使用以及查询优化前的注意事项。
首先抛出一个问题:为什么查询速度会慢?
相信很多人不能一气呵成的说完整吧? 其实我也不行 (四)查询性能优化 - John.Zhou - zhouyou.jun的博客,行的话,我有何必大篇幅整理呢?
是吧,哈哈。

1.  总括
查询性能低下的最基本的原因是访问的数据太多?——这个回答有点像脑筋急转弯吧,呵呵。
一般分析低性能查询的从两方面着手:
1) 确认应用程序是否在检索大量超过需要的数据(如额外的数据行或者列)。
2) 确认MySQL服务器层是否在分析大量超过需要的数据行。

2.  是否向数据库请求了不需要的数据行
通常的做法是分页亦或是利用 LIMIT 限制数据行数量。

3.  MySQL是否在扫描额外的数据
一般我们在WHERE条件中使用三种方式来过滤数据,从好到坏依次为
1) 索引中使用WHERE条件来过滤不匹配的记录。这是在存储引擎层完成的。
2) 使用索引覆盖扫描(在Extra列中出现了Using index)来返回记录,直接从索引中过滤不需
要的记录并返回命中的结果。,这是在MySQL服务器层完成的,但无需在再次回表查询记录。
3) 数据表中返回数据,然后过滤不满足条件的记录(在Extra列中出现Using Where)。这在
MySQL服务器层完成,MySQL需要先从数据表中堵住数据然后过滤。、

下面是经常使用到的一些技巧:
如果发现查询需要扫描大量的数据但是只返回少数的行,那么可以考虑如下手段:
1) 使用索引覆盖扫描,把所有需要用到的列都放到索引中,这样存储引擎无须回表获取对应行就
可以返回结果了。
2) 变数据库表结构设计。例如使用单独的汇总表。
3) 写这个复杂的查询,让MySQL优化器能够以更优化的方式执行这个查询(到后面回头看这个)。

4.  重构查询
概述:有时候分解查询非常重要,也很有必要。等会我会举两个场景。
4.1  切分查询
将一个很大的DELETE语句切分为多个较小的查询可以尽可能小地影响MySQL性能。如果每次删除数据
后,都暂停一下再做下一次删除,这样也可以将服务器上原本一次性的压力分散到一个很长的时间段
中,就可以大大降低对服务器的影响,还可以减少删除时锁的持有时间。
说明:上面话中将DELETE切分为查询,相信有人会疑惑吧?——UPDATE、DELETE本质上都是查询,
因为先要查找出来才能做吧。

4.2  查询执行的基础
我们发一条SQL,这条SQL的执行步骤是什么呢? 看如下示意图:
(四)查询性能优化 - John.Zhou - zhouyou.jun的博客
 
步骤描述如下:
a. 客户端发送一条SQL到服务器。
b. 服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果。否则进入下一阶段。
c. 服务器端口进行SQL解析、预处理、再有优化器生成对应的执行计划(Exec plan)。
d. MySQL根据优化器生成的执行计划,调用存储引擎的API来执行查询。
5.将结果返回(并存储在缓存中)。

4.2.1  查询优化器
MySQL和Oracle一样,现在都是是使用的基于成本的优化器。Oracle中叫CBO(成本优化器)。
可以使用  SHOW STATUS  LIKE  'last_query_cost'; 来查看当前(最后一次的查询)的查询成本。
(四)查询性能优化 - John.Zhou - zhouyou.jun的博客
 
与Oracle一样,我们可以使用Hint来强制改变优化器选择。后续会分析。
4.2.2  关联查询
关联查询可以参考额的Oracle系列里面的关联查询。

4.2.3  排序优化
无论如何排序都是一个成本很高的操作,所以从性能的角度,应该尽可能避免排序或者尽可能避免对
大量数据进行排序。
当不能使用索引生成排序结果的时候,MySQL需要自己进行排序,如果数据量小则在内存中排序,如果
数据量大就需要使用磁盘,不过MySQL把这个过程统一称为文件排序(filesort),即使完全是内存排
序不需要任何磁盘文件时也是如此。

5.  在同一个表上查询和更新
先来看一个SQL:


6.  COUNT() 优化
    在统计行数的时候,最好使用COUNT(*)。这种情况下通配符 * 并不会像我想象的那样扩展成所有列,实
际上会忽略所有的列而直接统计所有的行数。再说 COUNT(*) 这样的写法清晰,性能也很不错的。
     面临复杂的COUNT(*) 优化,特别是在大数据量的情况下,就可能要使用汇总表了。
7.  用户自定义变量
    用户自定义变量是一个用来存储内容的临时容器,在连接MySQL的整个过程中都存在。
    下面了解下常见的用法:

8.  查询优化前的提示
这里我从网上找些资料,贴在下面参考下:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值