导读
在数据库系统中,收到一个查询请求时,执行器会负责解析 SQL 语句,生成执行计划,然后再一步步实现我们的查询请求。分布式数据库拥有分布式执行计划,与传统单机数据库相比拥有更高的扩展性。本文将介绍 NewSQL KaiwuDB 的分布式计划生成机制。
数据库的服务端,可以划分为执行器 (Execution Engine) 和存储引擎 (Storage Engine) 两部分。其中,执行器负责解析 SQL 命令并执行查询。数据库收到查询请求后,需要先解析 SQL 语句,把这一串文本解析成便于程序处理的结构化数据,然后生成一个逻辑执行计划,最后再转换成和数据的物理存储结构相关的物理执行计划,从目标节点中调取所需的数据,从而完成整个数据查询的过程。
执行器执行之前,需要计划的支撑。计划分为逻辑计划和物理计划。逻辑计划与物理计划的关系就好比是我们要出去旅游,选择什么交通工具就相当于逻辑计划,在这一步比如选择了飞机后。选择哪家航空公司就相当于物理计划。最后,当你真正动身去旅游就相当于执行。图1 给出 SQL 语句执行的基本构架图,从中可以清楚地看到优化器和执行器在整个流程中的执行过程。
图1 sql 执行基本框架图
逻辑计划和物理计划负责生成执行计划和索引选择等功能,可以把它看做优化器。比如执行这样的语句,执行两个表的 join:
Select * from t1 join t2 using(ID) where t1.c = 10 and t2.d = 20;
既可以先从 t1 里取出 c=10 记录的 ID,再根据 ID 关联到 t2,再判断 t2 里面 d 的值是否等于 20,也可以先从 t2 里取出 c=20 记录的 ID,再根据 ID 关联到 t1,再判断 t2 里面 d 的值是否等于 10。这两种执行方法的逻辑是一样的,但执行效率不同,优化器可以预估代价决定使用方案。在分布式数据库中,其中的物理计划还可以根据要用到的数据 span 所在的节点判断该算子在哪个节点上执行,从而实现分布式执行。与分布式相关的物理计划具体作用在分布式执行概述。
同单机数据库相比,在执行计划方面,KaiwuDB 在生成逻辑计划时是相同的,而在由逻辑计划生成物理计划时会有较大的不同。当由逻辑计划生成物理计划时,会根据各个节点的数据分布,添加表信息和节点信息,生成分布式的物理计划。
分布式执行的关键思想是如何从逻辑执行计划到物理执行计划,这里主要涉及两方面的处理,一个是计算的分布式处理,一个是数据的分布式处理。
一旦生成了物理计划,系统就需要将其拆分并分布到各个 node 之间进行运行。每个 node 负责本地调度 processors 和 inputs。node 还需要能够彼此通信以将输出 output router 连接到 input。特别是,需要一个 streaming interface 来连接这些组件。为了避免额外的同步成本,需要足够灵活的执行环境以满足上面的所有这些操作,以便不同的 node 除了执行计划初始的调度之外,可以相对独立的启动相应的数据处理工作,而不会受到 gateway 节点的其他编排影响。
数据库的集群中的 Gateway node 会创建一个调度器,它接受一组 Flow,设置输入和输出相关的信息,创建本地 processor 并开始执行。在 node 对输入和输出数据进行处理的时候,我们需要对 Flow 进行一些控制,通过这种控制,我们可以拒绝 request 中的某些请求。
每个 Flow 表示整个物理计划中跨节点执行的一个完整片段,由 processors 和 streams 组成,可以完成该片段的数据拉取、数据计算处理和最终的数据输出。如图 2 所示:
图2 Flow 执行流程图
对于跨节点的执行,Gateway node 首先会序列化对应的 FlowSpec 为 SetupFlowRequest,并通过 GRPC 发送到远端 node,远端 node 接收后,会先还原 Flow,并创建其包含的 processor 和交互使用的 stream(TCP 通道),完成执行框架的搭建,之后开始由网关节点发起驱动的多节点计算。Flow 之间通过 box 缓存池进行异步调度,实现整个分布式框架的并行执行。
对于本地执行,就是并行执行,每个 processor,synchronizer 和 router 都可以作为 goroutine 运行,它们之间由 channel 互联。这些 channel 可以缓冲信道以使生产者和消费者同步。
为实现分布式并发执行,数据库在执行时引入了 Router 的概念,对于 JOIN 和 AGGREGATOR 等复杂算子根据数据分布特征,实现了三种数据再分布方式, 分别是 mirror_router、hash_router 和 range_router。通过数据再分布,实现了 processor 算子内部拆分为两阶段执行,第一阶段在数据所在节点做部分数据的处理,处理后的结果,根据算子类型会进行再分布,然后在第二阶段汇集处理,从而实现了单个算子多节点协作执行。
同单机数据库相比,KaiwuDB 的分布式执行计划使得数据库有着更高的扩展性,可以有效管理更多的数据,读写可以支持更大规模的数据集。
单机数据库的扩展性是有限的,在单机场景下,数据库在管理超大规模数据时会有较大的限制,读写的效率会随着表数据的增大而大幅降低。
而在分布式执行计划中,表数据被分散在多个节点上,这大大降低了单节点的数据量,在保存同样数据量的场景下,KaiwuDB可以充分利用多个节点的存储与计算资源。比如在单机场景下,对于某个复杂的表,可能在其数据量从 500 万行到 1 千万行的效率衰减十分严重,但在分布式场景下,均衡负载时该表被分配到多个节点上,各个节点的实际数据增量并不多,不会有单机场景下的突然性能衰退。
分布式执行计划还可以做到读写,计算的分布式执行。每个节点可以在自己的节点进行独立的计算,并将最后的结果综合得到准确的计算结果。在大部分场景下分布式执行比单机数据库的执行有着较大的优势。