CockroachDB开发学习文档04 SQL工作原理

目标:分析一个SQL语句的执行过程。

 

从目前的CRDB源代码来看,整个流程框架如下所示:
CockroachDB开发学习文档04 SQL工作原理_第1张图片

首先,要了解一下什么是AST树。

抽象语法树(abstract syntax code,AST)是源代码的抽象语法结构的树状表示,树上的每个节点都表示源代码中的一种结构,这所以说是抽象的,是因为抽象语法树并不会表示出真实语法出现的每一个细节,比如说,嵌套括号被隐含在树的结构中,并没有以节点的形式呈现。抽象语法树并不依赖于源语言的语法,也就是说语法分析阶段所采用的上下文无文文法,因为在写文法时,经常会对文法进行等价的转换(消除左递归,回溯,二义性等),这样会给文法分析引入一些多余的成分,对后续阶段造成不利影响,甚至会使合个阶段变得混乱。因些,很多编译器经常要独立地构造语法分析树,为前端,后端建立一个清晰的接口。

从CRDB的工作流程图来看,这些一个个planNode就是抽象的语法树节点。

打开pkg/sql/plan.go文件,找到planNode的定义:

type planNode interface {

 Start(params runParams) error

 Next(params runParams) (bool, error)

 Values() parser.Datums

 Close(ctx context.Context)

}

Start()函数的功能是初始运行当前节点,Next()函数相当于对下一行数据进行处理,得到的数据可以通过Values()进行读取,最后销毁节点时调用Close()。

这是一个接口类型,看看下面,定义了许多的全局变量,这些就是AST树上的节点,但都是空的,这里主要是做一些空节点的初始化。

再看一个接口类型, 

type planMaker interface {

    newPlan(ctx context.Context, stmt parser.Statement, desiredTypes []parser.Type,) (planNode, error)

    makePlan(ctx context.Context, stmt Statement) (planNode, error)

    prepare(ctx context.Context, stmt parser.Statement) (planNode, error)

}

通过这个planMaker就可以递归地对构建AST树了,一条复杂的SQL语句最后都是返回一个planNode的接口。

在得到根结点的planNode之后,CRDB会进行执行期优化,检测并判断当前SQL走的是单机工作流程还是分布式的工作流程。

通常,一些系统的查询就会走单机工作流程模式,直接调用startPlan()对根结点进行Start,Next,Values,Close的工作。

最后,通过一个ForEachRow()函数就可以对每行的数据进行相应的编排处理了。

而当数据分布在多节点上的时候,就会走分布式流程的结果。

比如一条简单的SELECT * FROM TABLE_NAME;

可以查看pkg/sql/executor.go文件,这里和单机的查询最大区别就是用了一个distSQLPlanner。

这个Planner能够将请求封装成runnerRequest,然后下发到节点上去处理。

而节点的具体处理逻辑在pkg/sql/distsqlrun/tablereader.go文件中进行了实现。

最后的数据就会由RowFetcher一行行地读出来。

你要是问我怎么知道是在这里找到的,请看

https://github.com/cockroachdb/cockroach/issues/27551

你可能感兴趣的:(Golang)