本文转载自微信公众号「匠心独运维妙维效」,分执行作者EverDB研发组。布式转载本文请联系匠心独运维妙维效公众号。计划 在数据库系统设计中,分执行执行计划是布式对SQL执行流程的形式化描述,包括了SQL执行需要的计划所有算子以及其执行次序。我们通过“EXPLAIN + SQL”指令可以详细地查看其执行计划,分执行找到性能瓶颈,布式为我们优化SQL提供方向和依据。计划本文将从EverDB分布式数据库角度阐述执行计划。分执行 相比于集中式数据库,布式分布式数据库拥有大量分片节点,计划分别负责各自分片的分执行数据计算与存储,那么其执行计划就需要特殊的布式实现方式。对于中间件架构分布式数据库,计划通过引入分布式算子(即下文EverDB执行计划节点)实现数据分片存储功能,执行计划解析优化,下发数据分片内部独立计算,协调数据分片之间并发执行,执行结果由中间件进行进一步整合进行分组、排序等操作,是一种高效便捷的实现方式。 EverDB正是基于这种设计思路实现的执行计划。与传统集中式数据库相比,EverDB执行计划使数据库有更高的网站模板扩展性,支持更大量级的数据规模,更高并发的数据访问。在处理相同负载压力的前提下,可以充分利用各分片的存储与计算资源,以及并行计算的优势达到更好的性能。 EverDB分布式数据库由Grid调度层、数据节点、配置节点、管理台组成。Grid调度层作为分布式数据库的调度节点,接收并解析SQL,将SQL语句重构改造,支持涉及分片表和非分片表两种类型的执行计划分析。 图1 EverDB的执行计划包括SQL在Grid调度层和后端数据节点的执行流程。Grid调度节点的执行计划,主要涉及逻辑处理层和连接驱动层两个部分,其中逻辑处理层包括词法、语法解析模块,客户端通信模块,普通表/分片表配置、SQL重构改造、服务器租用执行计划树及计划树节点。其中普通表/分片表配置用于识别SQL是否需要分片处理,并获取分片表的存储地址信息,完成基于分片策略的执行计划构建。连接驱动层是内部连接池和通信协议的处理模块,完美支持MySQL通信协议,负责在执行计划中将请求下推给数据节点。数据节点执行计划的实现方式可以参照MySQL执行计划。 图2 以分片查询为例,EverDB的Grid调度节点的执行计划流程: 图3 调度节点在生成执行计划树时,会根据分片规则对语句进行并行执行改造,将重构后的多条SQL由对应的执行计划树叶节点下推至目标实例,由数据节点实例完成该分片的查询执行计划分析。 图4介绍了执行计划叶节点将查询请求下推至数据节点的通讯流程。COM_QUERY是封装了查询语句的协议包,由执行计划树叶节点发送至对应的数据节点进行查询计算。执行计划叶节点以MySQL协议流程接收、解析结果集。图示中结果集返回的协议包及次序为: 执行计划叶节点收到分片的查询结果后,将各自分片结果交由父级非叶节点对所有分片结果做进一步处理(如归并、排序等),向客户端返回完整的查询数据结果。 图4 展示执行计划,只需在查询的SELECT关键字之前增加DBSCALE EXPLAIN。具体语法如下: DBSCALE EXPLAIN + SELECT查询语句; 结果包含执行计划每一步的执行信息,显示执行节点、执行次序和执行SQL内容,SQL性能好坏也能通过执行计划看出来。用于分析SQL语句和表结构的性能瓶颈。 图5 如上图(图5)示例,执行计划返回结果分为上下两个结果集。第一部分展示的是查询请求从中间层Grid到数据节点的完整执行计划。结果集前两列是SQL在中间层Grid的执行计划,即exec_node字段展示SQL的执行计划树,data_source展示的是每一个分片执行节点涉及的分片数据源。结果集其他字段则展示的是每一条分片查询在各自数据节点上的执行计划,这块与MySQLexplain的返回结果是相同的。第二部分展示的是执行计划在每个执行节点上实际运行的重构后SQL语句,因此可能与从客户端接收到的SQL语句不同。 select_type:查询数据的操作类型,如下表: SIMPLE 查询中不包含子查询或者UNION PRIMARY 查询中若包含任何复杂的子部分,最外层查询标记为PRIMARY SUBQUERY 在SELECT或WHERE列表中包含了子查询,该子查询被标记为SUBQUERY DERIVED 在FROM列表中包含的子查询被标记为DERIVED(衍生) UNION 若第二个SELECT出现在UNION之后,则被标记为UNION;若UNION包含在FROM子句的子查询中,外层SELECT将被标记为DERIVED UNION RESULT 从UNION表获取结果的SELECT被标记为UNION RESULT table:执行节点所处理的表名。 type:数据节点在表中找到所需行的方式,又称“访问类型”,表示| All | index | range | ref | eq_ref | const,system | null | 由左至右,由最差到最好。常见类型如下表: ALL Full Table Scan, 数据节点将遍历全表以找到匹配的行 Index Full Index Scan,index与ALL区别为index类型只遍历索引树 Range 索引范围扫描,对索引的扫描开始于某一点,返回匹配值域的行,常见于between、<、>等的查询 Ref 非唯一性索引扫描,返回匹配某个单独值的所有行。常见于使用非唯一索引即唯一索引的非唯一前缀进行的查找 Eq_ref 唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配;常见于主键或唯一索引扫描 Const、system 当数据节点对查询某部分进行优化,并转换为一个常量时,使用这些类型访问;如将主键置于where列表中,数据节点就能将该查询转换为一个常量,system是const类型的特例,当查询的表只有一行的情况下,使用system NULL 数据节点在优化过程中分解语句,执行时甚至不用访问表或索引 第二部分包括node_id和sql两个字段:node_id与第一部分中exec_node字段的中括号内序号相关联,表示exec_node每个层次中具体执行SQL语句。具体SQL语句内容则在“sql”字段中显示。 当“sql”字段中出现临时表dbscale_tmp时(dbscale_tmp为EverDB保留字),说明当前SELECT查询涉及跨分片查询,系统性能损耗较高,需要进一步分析SQL语句和表结构性能瓶颈,尽可能避免使用临时表,示例如下。 图6 EverDB作为一种典型的基于中间件实现分库分表方案的分布式数据库产品,其执行计划相比于传统集中式数据库的不同之处在于,既包括了SQL在底层各分片表上的执行步骤,也包含proxy如何将SQL进行分布式处理,提高分布式数据库的处理性能,是EverDB基于中间件对执行计划一种特有的实现方式。 EverDB执行计划不管从底层数据节点还是中间层,SQL优化算法方面,还有很多值得优化改进的地方。未来,EverDB会持续精进自身的各项能力,努力成为更出色的国产分布式数据库产品。(一)分布式架构执行计划
(二)EverDB执行计划
(三) 如何查看执行计划?
四 总结