一、为什么查询速度会慢?
如果把查询看作是一个任务,那么它由一系列子任务组成,每个子任务都会消耗一定的时间。如果要优化查询,实际上要优化其子任务,要么消除其中一些子任务,要么减少子任务的执行次数,要么让子任务运行的更快。
二、优化数据访问
2.1 是否向数据库请求了不需要的数据
- 查询了不需要的记录
- 多表关联时返回全部列
- 总是取出全部列
- 重复查询相同的数据
2.2 MySql是否在扫描额外的记录
对应mysql中最简单的衡量查询开销的三个指标如下:
- 响应时间
扫描的行数
返回的行数
2.3 Mysql应用where条件,从好到坏依次为:
- 在索引中使用where条件来过滤不匹配的记录。这是在存储引擎层完成的
- 使用索引覆盖扫描来返回记录,直接从索引中过滤不需要的记录并返回命中的结果。这是在Mysql服务层完成的,但无需再回表查询记录。
- 从数据表中返回数据,然后过滤掉不满足条件的记录。这在Mysql服务层完成。Mysql需要先从数据表读出记录然后过滤。
2.4 查询优化的一些技巧
- 使用索引覆盖扫描。把所有需要的列都放在索引中,这样存储引擎无需回表获取对应行的数据就可以返回结果了。
- 改变库表结构。例如使用单独的汇总表
- 重写这个复杂查询,让Mysql优化器能够以更优化的方式执行这个查询
3 重构查询优化
3.1 使用一个复杂的查询还是多个简单的查询
在传统认知中,总是强调需要数据库层完成尽可能多的工作,这样做的逻辑在于以前总是认为网络通信、查询解析和优化是一件代价很高的事情。但是对于Mysql来说并不适用。Mysql从设计上让连接和断开连接都很轻量级,在返回一个小的查询结果方面很高效。
但是不要为了拆分而拆分。我们看到有些应用对一个数据表做10次独立的查询返回10行数据,每个查询返回一条结果,查询10次就完全没必要了。
3.2 切分查询
如: 删除旧数据,定期清除大量数据会一次性锁住很多数据,占满整个事务日志,间隔删除部分数据可以将服务器上原本一次性的压力分散到一个很长的时间段。
3.3 分解关联查询
在很多场景下,通过重构查询将关联放到应用程序中将会更加高效,这样的场景有很多,比如:当应用能够很方便地缓存单个查询的结果的时候,当可以将数据分布到不同的Mysql服务器上时候,当能够使用IN()的方式替代关联查询是,当查询中使用同一个数据表时。
4 查询执行流程
- 客户端发送一条查询给服务器
- 服务器先检查查询缓存,如果命中缓存,则立刻返回存储在缓存中的结果。否则进行下一阶段
- 服务器进行Sql解析,预处理。再由执行器生成对应的执行计划。
- Mysql根据优化器生成的执行计划,调用存储引擎的API来执行查询
- 将结果返回给客户端。