SQL的执行过程简析
对于这个执行过程,过去总是模糊不清,含糊的知道,会有SQL语法解析,执行计划分析等等。近日在工作中有相关学习,故写此文记录。
SQL
SELECT id,name,age FROM Users WHERE id = 18;
先来看这样一句SQL,在人的角度可以从中获取几个关键信息:这是一个“SELECT”操作,从特定的某张表里,需要取出一系列字段,并且附加有查询条件。
而数据库无法直接从字符串中解析出这些信息,它需要做一些额外的处理。
词法分析 lexer
首先需要先解析SQL中的关键字,例如 SELECT、FROM、WHERE、以及SQL中涉及的字段、表达式等。
而具体的关键字,是需要被定义的,例如可以采用YYAC的格式进行定义:
%token <ident>
invalid
explainKwd "EXPLAIN"
selectKwd "SELECT"
insertKwd "INSERT"
updateKwd "UPDATE"
deleteKwd "DELETE"
into "INTO"
values "VALUES"
set "SET"
词法分析就能从SQL语句中,将关键字提取成为token,这些token,就是后面语法分析需要用到的了。
语法分析 parser
拿到了token,相当于士兵收到了具体的命令,但是士兵并不知道这些命令能否进执行,它需要判断命令是否符合格式标准。
比如 select后面要么是字段、要么是*,不能紧接着就是WHERE。
这些格式定义同样需要声明:
SelectStmtBasic:
"SELECT" SelectOpt FieldList
{
fields := &ast.FieldList{Fields: $3.(*ast.SelectFieldList).List}
st := &ast.SelectStmt{
SelectOpt: $2.(*ast.SelectOpt),
Distinct: $2.(*ast.SelectOpt).Distinct,
Fields: fields,
}
$$ = st
}
以select为例,SELECT关键字后面,需要是 SelectOPt(例如 DISTINCT),和字段列表。如果语法解析器无法从定义中找到匹配的,那么说明这段SQL是无效的。
而如果能够匹配到对应的规则,那么语法解析器就会生成对应的抽象语法数节点。例如 select节点,它拥有一个fileds子节点,记录了要查询哪些字段,还有Distinct节点记录了是否需要进行去重。
而当整个SQL都被解析为AST(抽象语法树)之后,语法解析器的工作也就完成了。
执行优化器
对于一行SQL,只看它的ast,我们只能解析出,它要做什么;但是通往罗马的道路不止一条,数据库需要选择出最优的执行方案。
例如:
SELECT name,age FROM Users WHERE name = "Kaniu"
在name建立了索引的情况下,那么就可以通过访问name字段的索引,去进行检索,然后拿着主键id,再回表去拿到age。
这是其中一种方案,但它并不一定是最好的,有人可能会疑惑,索引不是能优化性能吗,这肯定就是最好的执行方案了呀。
在通常情况下,可能索引性能更好,但是如果这张Users只有1条数据,
如果还走索引的话,不仅需要走一遍name的索引,还需要回表到主键索引。而如果采用全表扫描的话,那么一次访问就可以了。
所以 这就是执行优化器存在的意义。它会根据数据库的统计信息,分析出开销最小的执行方案。
执行引擎 与 存储引擎
有了具体的执行方案,那么就需要开始干活了。执行引擎就是负责实现具体操作的。例如SORT操作,执行引擎就会采用对应的算法将数据排序。而存储引擎,则是提供原始数据的。例如要执行按索引过滤,那么执行引擎就需要从存储引擎中,将索引加载到内存。
在这一步执行完毕后,数据也被按照SQL中的要求进行过滤、排序、分组了。就可以将数据返回给客户端了。
- 0
- 0
-
分享