通常来说,查询的生命周期大致可以按照顺序来看从客户端到服务端,然后在服务器上进行解析,生产执行计划,
执行,并返回结果给客户端。其中的执行阶段可以认为是整个生命周期中最重要的阶段,其中包括了大量为了检索
数据到存储引擎的调用以及调用后的数据处理,包括排序、分组等。
在完成这些任务的时候,查询需要在不同的地方花费时间,包括网络、CPU计算、生成统计信息和执行计划、锁等待
等操作,尤其是底层存储引擎检索数据的调用操作,这些调用需要在内存操作、CPU操作和内存不足时导致的I/O操作
上。
1、是否向数据库查询了不需要的数据
在访问数据库时,应该只请求需要的行和列,请求多余的行和列会消耗MySQL服务器的CPU和内存资源增加网络开销。
1-1、 在处理分页时,应该使用limit 限制MySQL只返回需要的数据,而不是返回全部数据再由程序过滤
1-2、 多表关联时,或获取单表数据时,尽量避免select *
1-3、 当某些数据被多次使用时,考虑将其缓存。
2、查询数据的方式有全表扫描、索引扫描、范围扫描、唯一索引查询、常数引用等。这些方式从慢到快。
3、分解复杂的查询
将大查询切分成多个小查询执行,每个小查询只完成整个查询任务的一小部分,每次只返回一小部分结果
二、查询执行的流程
1、客户端发送一条查询给服务器
2、服务器先检查查询缓存,如果命中了缓存,则立刻返回缓存中的结果。
3、服务器段进行SQL解析、预处理、优化器生成对应的执行计划
4、MySQL根据优化器生成的执行计划,调用存储引擎的API来执行查询
5、将结果返回
上述过程抽象化,先再结合具体的方法来说明:
1、通信协议
客户端和服务端二者之间的通信协议方式是半双工的,即二端只能单向发送数据,不能同时双向。并且,一端
开始发送信息时,另一端接受完整消息才能响应它。
2、查询状态
一个查询过程,在其过程中分为多个状态
2-1、sleep 线程正在等待客户端发送新的请求
2-2、query 线程正在执行查询或者正在将结果发送给客户端
2-3、locked 该线程正在等待表锁
2-4、analyzing and statis 线程正在收集存储引擎的统计信息,并生成查询的执行计划
2-5、copying to temp table 线程正在查询,将结果集都复制到一个临时表中。一般是在做group by union
2-6、sorting result 线程对结果集进行排序
2-7、sending data 线程可能在多个状态之间传送数据,或者生成结果集火灾在客户端发送请求。
3、SQL解析和预处理主要验证是否使用了错误的关键字、语法是否有误、数据表和数据列是否存在,名称和别名是否
有歧义。 当语法验证都是合法之后,优化器会将SQL转化为执行计划。