文档介绍:如何理解 Mysql 执行计划肖武 我们已经能够用 tcpdump+ percona tookit 的 pt-query-digest 来获取 mysql 的语句。在得到查询比较慢的 sql 时,我们需要知道查询慢在哪? 目录?引导? mysql 逻辑系统结构?查询的过程以及开销?查询性能低下的基本原因? sql 的标准执行流程? sql 中的 join ? nested loop join 算法? Explain 输出? type ? Keys ? others ? extra ?案例分析?案例分析?补充说明 Mysql 的逻辑体系结构查询的过程以及开销查询的过程从客户端到服务端,在服务器上进行解析,生成执行计划,执行,并返回结果给客户端,执行包括了大量为了检索数据到存储引擎的调用以及调用后的数据处理,包括排序,分组查询的开销 的解析,优化,锁等待,以及数据处理等 2. 存储引用的 API 的调用查询性能低下的原因查询效率低下的最基本的原因是访问的数据量过大。 1、应用查询时,请求了不需要的数据-查询不需要的记录( limit 解决) - 多表连接时返回所有列 - 总是取出所有列-重复查询(缓存解决) 2、 mysql 扫描了额外的记录-扫描的行数以及返回的函数(读选比) -扫描的函数以及访问的类型访问类型,可以反应从表中找到一行记录的的成本。有表扫描,索引扫描,范围扫描,唯一性索引查询,常数引用。代价从高到低,扫描的行数由多到少提高查询的效率: 应用逻辑调整,尽可能取需要的数据,另外让 mysql 找到合适的访问类型,用最小的代价找到所需要的记录数 SQL 标准的执行流程(select) 标准的执行流程(8)SELECT (9)DISTINCT (11)<TOP_specification> <select_list> (1)FROM <left_table> (3)<join_type> JOIN <right_table> (2) ON <join_condition> (4)WHERE <where_condition> (5)GROUP BY <group_by_list> (6)WITH {CUBE ROLLUP} (7)HAVING <having_condition> (10)ORDER BY <order_by_list> SQL 标准的执行流程?1 FROM: 对 FROM 子句中的前两个表执行笛卡尔积,生成虚拟表 VT1 。 2 ON: 对 VT1 应用 ON 筛选器。只有那些使<join_condition> 为真的行才被插入 VT2 。 3 OUTER(JOIN): 如果指定了 OUTERJOIN ,保留表中未找到匹配的行将作为外部行添加到 VT2 ,生成 VT3 。如果 FROM 子句包含两个以上的表,则对上一个联接生成的结果表和下一个表重复执行步骤 1到步骤 3, 直到处理完所有的表为止。 4 对 VT3 应用 WHERE 筛选器。只有使<where_condition> 为 TRUE 的行才被插入 VT4 。 5 GROUP BY: 按 GROUP BY 子句中的列列表对 VT4 中的行分组,生成 VT5 。 6 CUBEROLLUP: 把超组插入 VT5 ,生成 VT6 。 7 HAVING: 对 VT6 应用 HAVING 筛选器。只有使<having_condition> 为 TRUE 的组才会被插入 VT7 。 8 SELECT: 处理 SELECT 列表,产生 VT8 。 9 DISTINCT: 将重复的行从 VT8 中移除,产生 VT9 10 ORDER BY: 将 VT9 中的行按 ORDER BY 子句中的列列表排序,生成一个有表(VC10) 。 11 TOP: 从 VC10 的开始处选择指定数量或比例的行,生成表 VT11, 并返回给调用者。 PS: from 的笛卡尔积资源消耗巨大, mysql 进行了优化,后面会提到 9 sql 中的 join 连接类型 Left join Right join Inner join Outer join nested loop join 算法(对连接的优化) 在 mysql 中,只有一种 Join 算法,就是大名鼎鼎的 Nested Loop Join ,他没有其他很多数据库所提供的 Hash Join ,也没有 Sort Merge Join 。顾名思义, Nested Loop Join 实际上就是通过驱动表的结果集作为循环基础数据,然后一条一条的通过该结果集中的数据作为过滤条件到下一个表中查询数据,然后合并结果。如果还有第三个参与 Join ,则再通