第六章—查询性能优化
为什么查询会变慢
如果查询是一个任务,那么它由一系列子任务组成,每个子任务都会消耗时间,优化查询其实就是优化子任务 要么消除一些子任务;要么减少一些子任务执行的次数;要么加快子任务的执行速度
慢查询基础:优化数据访问
查询性能低下的最基本原因就是访问的数据太多,可以这样分析:
- 是否查询了大量超过需要的数据
- mysql是否在服务器层分析了大量超过需要的数据行
是否向数据库请求了不需要的数据
- 查询不需要的记录: 一个常见的误解就是,以为mysql只会返回需要的数据,实际上是mysql先返回全部结果集再进行计算(使用limit可以减少mysql访问的数据)
- 多表关联时返回全部列: 多表关联时少用
*
,应该只选择实际需要的列,并且join
操作会加入额外的列 - 需要关联查询时,确保ON、USING里面的列上有索引
- 确保GROUP BY、ORDER BY的表达式只涉及一个表中的列
- 重复查询相同的数据 对于需要重复查询的数据,应该缓存起来
如果发现扫描了大量数据,却只返回少量的数据行,可以这样优化
- 将需要的列设为索引,这样就可以只扫描索引,无需回表
- 改变库表结构
太多的表会涉及关联操作,已经说了,关联操作很耗费资源,mysql会扫描很多没有必要的数据行 可以通过反范式,增加一些冗余字段,来减少表的连接 或者不要把表拆的很小
优化要检索的数据
- 只返回必要的列:最好不要使用 SELECT * 语句
- 只返回必要的行:使用 LIMIT 语句来限制返回的数据
- 缓存重复查询的数据:使用缓存可以避免在数据库中进行查询,特别在要查询的数据经常被重复查询时,缓存带来的查询性能提升将会是非常明显的
- 使用覆盖索引
切分大查询
- 不要强调要数据库完成尽可能多的任务,对于mysql,它是不使用的。 一个大查询如果一次性执行的话,可能一次锁住很多数据、占满整个事务日志、耗尽系统资源、阻塞很多小的但重要的查询
- mysql的连接和断开都很轻量级
- 对于一个小的查询很高效,每秒可以查询10万多条的数据,在内存中每秒可以查询上百万行数据
- 所以对于mysql,有时候将一个查询拆成多个小查询是很高效的
查询优化处理
COUNT()的作用
- 统计某个列值的数量(列要非空)
- 统计行数(count(*)就是在统计行数)