1、为什么查询速度会慢
优化查询,实际上要优化其子任务,要么消除其中的一些子任务,要么减少子任务的执行次数,要么让子任务运行得更快。
查询生命周期:客户端-》服务器-》查询解析-》生成执行计划-》执行-》返回结果。
2、慢查询基础:优化数据访问
查询性能地下最基本的原因是访问的数据太多。某些查询可能不可避免的需要刷选大量数据,但这并不常见。大部分性能地下的查询都能够通过减少访问的数据量的方式进行优化。对于地下的查询,可以通过两个步骤分析:
1、确认应用程序是否在检索大量查过需要的数据。
访问太多的行(实际用户只查看几页,但是把所有的数据都返回了)或者太多的列(返回只需要的数据)。
查询过多的数据会消耗额外的资源。
常见案例:
查询不需要的记录(考虑使用limit)
多表关联时返回全部列(只取需要的列,避免使用select *)
总是取出全部列(避免select *)
重复查询相同数据(使用缓存,避免多次查询同样数据)
2、确认mysql服务器层是否在分析大量查过需要的数据行。
衡量查询的三个指标:
响应时间(服务时间+排队时间:查询话费时间+等待资源时间)
扫描行数
返回行数
使用explain 命令,通过返回的type总段反应访问类型(全表扫描、索引扫描、范围扫描、唯一索引查询、常数引用,速度慢变快)
如果查询没有找到合适的访问类型,那么solution 可以是增加一个合适的索引。
如果发现查询需要扫描大量的数据但是返回少量的行,那么可以使用下面技巧优化:
使用索引覆盖扫描,改变库表结构,重写复杂查询(优化sql)。
3、重构查询方式
1、是否讲一个复杂查询分成多个简单查询
2、切分查询。例如:
定期删除大量数据时,如果用一个大的语句一次完成,可能需要锁住很多数据,占满整个事务日志,耗尽系统资源、阻塞很多小的但是重要的查询。
将一个大的DELETE语句切分成多个较小的查询可以尽可能小的影响mysql性能,还可以减少mysql复制的延迟。
3、分解关联查询
很多高性能应用都会对关联查询进行分解。简单的,可以对每一个表进行一次单表哈寻,然后将结果在应用汇总关联。
select * from tag join tag_post on tag_post.tag_id=tag.id join post on tag_post.id=post.id where tag.tag='mysql';
分解成小查询
select * from tag where tag='mysql'
select * from tag_post where tag_id=1234
select * from post where post.id in (123m456m789,9098)
然后通过应用来将多个结果集合并。
分解关联查询优势:充分利用缓存、单个查询减少锁竞争、应用层关联可以对数据库拆分,提高性能和扩展、查询本身效率可能会提升、较少冗余记录,这样详单与在应用中实现hash关联,而不是mysql的嵌套循环,某些场景hash关联效率高很多、
4、查询执行的基础
5、mysql查询优化器的局限性
关联子查询实现非常糟糕,最糟糕的是where条件中包含IN()的子查询。
按条件分析、多测试来验证猜想。
等值传递、并行执行、哈希关联等实现都不是很尽人意。
........
6、查询优化器的提示(hint)
使用一些特定的关键字,例如:SQL_CHCHE、for update、lock in share mode等。
7、优化特定类型的查询(279/800)
优化count()查询
优化关联查询
优化子查询
优化groupby 和distinct
优化limit分页
。。。。。。