查询性能优化
1.基本原则:优化数据访问
1)请求了不需要的数据
提取超过需要的列
多表连接时提取所有列
2)mysql检查了过多的数据
三大指标:执行时间、检查的行数、返回的行数
检查的行和返回的行:
通常不对应,比如连表查询;
检查的行和访问类型
mysql会在3中情况下实用where子句,从最好到最坏依次是:
对索引查找应用where子句来消除不匹配的行,发生在存储引擎层。
使用覆盖索引(extra为“using index”)来避免访问行,并且从索引取得数据后过滤掉不匹配的行。发生在服务器层,但是他不需要从表中读取行。
从表中检索出数据,然后过滤掉不匹配的行(在extra列中是“using where”)。发生在服务器端并且要求在过滤之前读取这些行。
如果发现访问的数据行数很大,而生成的结果中数据行很少,那么可以尝试更复杂的修改:
使用覆盖索引,它存储了数据,所以存储引擎不会去获取完整的行
更改架构;
重写复杂的查询,让mysql的优化器可以以优化的方式执行它。
2.重构查询的方式
1)复杂查询和多个查询
衡量两个之间的关系,是把复杂查询多个化,还是多个查询一个3化
2)缩短查询
举个例子:
巨大查询 delete from messages where created < data_sub(now(),interval 3 month);
应用伪代码查询替代
rows_affected = 0
do {
rows_affected = do_query(
"delete from messages where created < date_sub(now(),interval 3 month) limit 10000"
)
}
对于一个高效的查询来说,一次删除10000行数据的任务已经足够大。足够短的任务对服务器的影响最小。在delete语句中加入休眠语句也是一个好主意,它可以分摊负载,并且减少锁住资源的时间。
3.分解联接
将多表联查分解为小查询,在客户端进行合并。
优点:
1)缓存的效率更高。
2)对myisam表来说,每个表一个查询可以更有效的利用表锁,因为查询会锁住单个表较短时间,而不是把所有表长时间锁住。
在应用程序段进行连接可以方便的扩展数据库,把不同的表放在不同的服务器上面。
3)查询本身会更高效。
可以减少多余的行访问。连接查询是非正则化,反复的访问同一行数据。在应用程序端进行连接意味着对每行数据只会访问一次。
4)从某种意义上,可以认为这种方式是手工执行哈希连接,而不是mysql内部执行连接操作时采用的嵌套循环算法。哈希连接效率更高。
场景(在程序端进行连接效率更高):
1)可以缓存早期查询的大量数据。
2)使用了多个myisam表。
3)数据分布在不同的服务器上
4)对于大表使用in()替换连接。
5)一个连接引用了同一个表很多次。
4.查询执行基础知识
mysql执行查询的一般性过程:
1)客户端将查询发送到服务器。
2)服务器检查查询缓存。如果找到了,就从缓存中返回结果,否则进行下一步。
3)服务器解析,预处理和优化查询,生成执行计划。
4)执行引擎调用存储引擎api执行查询。
5)服务器将结果发送回客户端。