1 查询速度慢的原因
查询速度慢的原因有很多,比如网络、IO、CPU、上下文切换、系统调用、生成统计信息(profile和performance schema等)、锁等待。
2 数据访问优化
查询性能低下的主要原因是访问的数据太多,某些查询不可避免地需要筛选大量的数据,我们可以通过减少访问数据量的方式进行优化。需要确认应用程序是否在检索大量超过需要的数据,以及MySQL服务器层是否在分析大量超过需要的数据行。
向数据库请求了不需要的数据有以下情况:
- 查询不需要的记录,我们常常会误以为MySQL会只返回需要的数据,实际上MySQL却是先返回全部结果再进行计算,在日常的开发习惯中,经常是先用select语句查询大量的结果,然后获取前面的N行后关闭结果集,优化方式是在查询后面添加limit。
- 多表关联时返回多个表的全部列。
- 查询时使用select *。
- 重复查询相同的数据,可以使用缓存解决。
3 执行过程优化
3.1 查询缓存
在解析一个查询语句之前,如果查询缓存是打开的,那么mysql会优先检查这个查询是否命中查询缓存中的数据,如果查询恰好命中了查询缓存,那么会在返回结果之前会检查用户权限,如果权限没有问题,那么mysql会跳过所有的阶段,就直接从缓存中拿到结果并返回给客户端。需要注意的是,MySQL从8.0开始已经放弃了缓存。
3.2 查询优化器
当语法树没有问题之后,相应的要由优化器将其转成执行计划,一条查询语句可以使用非常多的执行方式,最后都可以得到对应的结果,但是不同的执行方式带来的效率是不同的,优化器的最主要目的就是要选择最有效的执行计划。
优化方式一般有基于成本的优化(CBO)和基于规则的优化(ROB),MySQL使用的是基于成本的优化器,在优化的时候会尝试预测一个查询使用某种查询计划时的成本,并选择其中成本最小的一个。其优化类型有以下几种:
- 重新定义关联表的顺序,数据表的关联并不总是按照在查询中指定的顺序进行,决定关联顺序是优化器很重要的功能。
- 将外连接转化成内连接,内连接的效率要高于外连接。
- 使用等价变换规则,MySQL可以使用一些等价变化来简化并规划表达式。
- 优化count()、min()、max(),索引和列不可为空通常可以帮助MySQL优化这类表达式,例如:要找到某一列的最小值,只需要查询索引的最左端的记录即可,不需要全文扫描比较。
- 预估并转化为常数表达式,当mysql检测到一个表达式可以转化为常数的时候,就会一直把该表达式作为常数进行处理。
- 索引覆盖扫描,当索引中的列包含所有查询中需要使用的列的时候,可以使用覆盖索引。
4 特定类型的查询优化
- 优化关联查询:当表A和表B使用列C关联的时候,如果优化器的关联顺序是B、A,那么就不需要再B表的对应列上建上索引,没有用到的索引只会带来额外的负担,一般情况下来说,只需要在关联顺序中的第二个表的相应列上创建索引。
- 确保任何的group by和order by中的表达式只涉及到一个表中的列,这样mysql才有可能使用索引来优化这个过程。
- 优化子查询:子查询的优化最重要的优化建议是尽可能使用关联查询代替。
- 优化limit分页:在很多应用场景中我们需要将数据进行分页,一般会使用limit加上偏移量的方法实现,同时加上合适的orderby 的子句,如果这种方式有索引的帮助,效率通常不错,否则的化需要进行大量的文件排序操作,还有一种情况,当偏移量非常大的时候,前面的大部分数据都会被抛弃,这样的代价太高。要优化这种查询的话,要么是在页面中限制分页的数量,要么优化大偏移量的性能。