SQL引擎是云溪数据库核心系统之一,主要包括三部分:解析器、优化器、执行器,它处理客户端传来的命令,解析器将命令解析编译成数据库能识别运行的命令,优化器将命令进行优化,优化的优劣直接影响数据库的性能,执行器最后进行执行命令。
一条SQL语句的生命周期:
图1 SQL执行流程
从图1可以看出,一条语句在数据库中的执行过程如下:
(1)数据库接收客户端传来的语句文本;
(2)经过词法解析得到一组词条;
(3)词条经过语法解析得到语法树(Abstract Syntax Tree,AST);
(4)AST经过语义解析得到表达式供优化器使用;
(5)经过规则优化(Rule-Based Optimization,RBO),主要是做查询的重写,如表达式化简,谓词下推等;
(6)再经过代价优化(Cost-Based Optimization,CBO)得到最优的查询表达式,此过程主要是列举所有路径并计算各路径的代价,选择代价最小的路径作为计划构建的基础;
(7)构建逻辑计划再构建物理计划;
(8)执行器执行计划;
(9)返回结果。
SQL解析器:
所有进入数据库的语句都需要经过解析的过程,才能被数据库所识别,解析器主要包括三部分:词法解析、语法解析、语义解析。
词法解析:
词法解析的任务是从左到右一个字符一个字符地读入解析程序,对字符流进行扫描然后根据构词规则识别字符并切割成一个个词条,切词的规则是遇到空格进行切割,遇到“;”结束词法解析。
Example: SELECT a FROM test WHERE a > 4;
通过词法解析后,该SQL语句被切割成以下词条:
语法解析:
语法分析的任务是在词法分析的结果上将词条序列组合成各类语法短句,组成的短句将与既定的语法规则进行匹配,若匹配成功则生成对应的抽象语法树(Abstract Syntax Tree,AST),否则报语法错误。
Example:
存在以下simple_select_clause的既定规则:
图2 simple_select_clause语法规则
图2规则中红色标记的都是终结符,一般是大写的关键字以及符号等,小写的是非终结符,一般用作规则的命名。
进行语法解析时,会将词法解析生成的词条逐一移进,每移进一个词条都会进行匹配规则的操作,如果匹配得上就会进行规约操作,否则继续进行移进,直到所有词条移进完毕且成功规约则解析完毕,生成对应的语法树。
例如词法解析得到词条如下:
语法解析先移进SELECT词条,无规约且剩余词条,继续移进;移进词条a,a可以规约成tartet_list,进行规约操作,用tartet_list替代词条a,还剩余词条,继续移进;移进FROM,无规约且剩余词条,继续移进;移进test,test可以规约成from_list,进行规约操作,用from_list替代词条test,然后from和from_list还可以规约成from_clause,继续进行规约操作,还剩余词条,继续移进;移进WHERE,无规约且剩余词条,继续移进;移进a,a可以规约成expr,用expr替代a,剩余词条,继续移进;继续移进>,无规约且剩余词条,继续移进;继续移进4,4可以规约成expr,用expr替代4,此时expr>expr可以规约成a_expr,用a_expr替代expr>expr,然后where和a_expr规约成where_clause,最终SELECT和target_list和from_clause和where_clause规约成simple_select_clause,至此解析完毕,而后生成对应的语法树。
语义解析:
语义分析的任务是对语法解析得到的语法树(AST)进行有效性审查,如表、列、列类型、函数、表达式等进行检查。
例如查询语句:SELECT a FROM test WHERE a > 4;
针对上面的例子将会审查三个地方:
1、from_clause;审查语句中的表test是否存在;
2、target_list;审查a列是否是from子句某个关系或视图的属性;
3、where_clause;审查a列是否是from子句某个关系或视图的属性且a列的类型是否能进行>4的比较操作。
语义解析结束后会生成对应表达式供优化器使用。