一般语句的优化
避免查询无意义的数据
避免使用 SELECT * ... 的做法
这样,很多时候查询出来的字段,数据是冗余的,是没有意义的,会消耗网络、CPU、内存等等。
利用索引,避免大量扫描表
如果要查询某些字段,但是查询这些字段的数据时,会大量的扫描这个表,耗费的资源太大了,怎么办呢?
我们应该建立合适的索引,避免大量的扫描表。
切分查询
比如,我每3个月要删除大约1000000条数据,如果直接写为:
DELETE FROM table where create_time < DATE_SUB(NOW(),INTERVAL 3 MONTH)
因为数据量庞大,sql的执行会花费大量时间,可能一次需要锁住很多数据,耗尽系统资源,同时阻塞很多小的但是很重要的查询。
明智的做法如下:
$rows_affected=0;
do{
$rows_affected=do_query("
DELETE FROM table WHERE create_time<DATE_SUB(NOW(),INTERVAL 3 MONTH LIMIT 10000)
")
}while($rows_affected>0)
Mysql执行查询的基础
Mysql的查询流程一般分为下面几步:
- 客户端发送一条查询给服务器
- 服务器查询缓存,如果命中,直接返回缓存结果,如果不命中,继续
- 服务器经过解析、预处理等,经过查询优化器生成查询计划
- 查询引擎,调用不同的API(MyISam、InnoDB等),来执行查询
将结果返回给客户端
总体可以总结为:
发送SQL—>查询缓存—>优化器生成sql—>引擎执行sql—>返回结果
Mysql客户端、服务器通信协议
Mysql客户端与服务器之间的通信是半双工的,即客户端和服务器不能同时发生通信。
一个人获得了球后,另一个人要等待传球。
同样
客户端发送了查询请求,要等待着服务器端返回数据。
服务器端返回完了数据,客户端才能再发送请求。
一般地,默认将服务器端返回的结果存储在服务器端的缓存中,但是,也可以使用函数,不缓存,直接返回给客户端。
存在缓存中,会消耗内存,但是服务器端的处理速度会加快。
不存在缓存中,不会消耗内存,但是服务器端处理的速度回减慢。
…待续