优化数据访问
是否向数据库请求了不需要的数据
- 查询不需要的记录
- 多表关联是返回全部列
- 总是取出全部列 ,尽量不要使用select *,去除全部列,可能会使优化器无法完成索引覆盖扫描这种优化.还会为服务器带来额外的IO,内存和cpu开销.
- 重复查询相同的数据.可以将经常用到的数据放在缓存里,避免重复查询数据库
是否在扫描额外的数据
确定了查询的数据列后,还应该看看查询是否为了返回结果是否扫描了过多的数据.对于mysql,最简单的衡量开销指标有三个:- 响应时间 包括服务时间(就是查询时间)和排队时间(也就是等待锁或者等待其他I/O完成的时间)
- 扫描行数
- 返回行数
对于查询最好的就是扫描行数/返回行数在1:1到10:1之间
可以尝试使用索引覆盖扫描,把所有需要的列放入索引中,这样存储引擎就可以不需要回表就可以返回列,或者重写查询.以更优的方式查询结果
重构查询的方式
- 考虑是用一个大的查询还是用很多个小的查询.因为在实际应用中,如果一个查询很大的话可能会导致锁住整个表,耗尽系统资源,阻塞后面的查询.因此有时候可以使用多个小的查询来返回结果,最后在把小的查询组合起来.
- 分解关联查询,因为每个数据库都有自己的缓存,如果分解大的查询可以更好的应用自己的缓存
mysql查询执行过程
- 客户端向服务器发送一条消息(这是半双工的,意思是同一时间只有一方能够发送数据)
- 服务器先查询缓存,如果缓存命中,直接返回给客服,否则进入下一阶段
- 服务端进行sql解析,预处理,在根据优化器生成对应的查询计划
- 调用存储引擎API查询数据,
- 将结果返回给客户端.
mysql能处理的优化类型
- 重新定义关联表的顺序
- 将外部连接转化程内部连接
- 使用等价变换规则, 比如 5=5 and a>5 换成 a>5
- 优化count(),min(),max(),如果在索引列找最小值,直接搜索最左边的值
- 覆盖索引查询,如果索引的列包含所有要查询的列的时候就无须在回表查询
- 子查询优化
- 提前终止查询: 比如使用limit语句的时候,发现语句够了,就会直接终止
- 列表in的比较,在mysql中,会把在in中的数据进行排序,然后在根据二分查找来查询,明显提高了查找速度.