本文属于SQL Server T-SQL执行内幕系列
接上文,当请求被任务接收同时得到工作线程指派执行后,就开始在SQL Server内部进行运作。当请求被执行时,第一步就是要先解析(Parsing)请求,把TDS数据流转换成SQL Server可识别的格式。
从客户端发送的是T-SQL文本,然后转换成TDS数据流,到达SQL Server之后变回T-SQL文本。但是由于纯T-SQL文本是“类英语的声明式语言”,SQL Server仍旧无法理解,需要再次解析为一种叫抽象语法树(https://en.wikipedia.org/wiki/Abstract_syntax_tree)的结构。在解析过程中,是以请求(request)为单位进行解析和编译。
如果这个阶段出现错误,整个请求就会终止。此时请求和任务标识为完成状态,对应的worker被释放然后用于执行其他pending的任务。
如果解析成功之后,就进行编译(compilation)操作。
SQL语言(不仅T-SQL)可以具有很复杂的语句,如大量JOIN等。同时SQL并非接近机器指令的语言,所以不是类似CLI指令或JVM字节码这类可执行代码,要执行SQL命令,实际上是使用数据访问计划(data access plans,https://en.wikipedia.org/wiki/Query_plan),常称查询计划或执行计划(Query plan /Execution plan),这种计划描述了如何打开表和索引,查询和定位所需的行和其他包含在请求中的数据操作的一个路线。比如,某个执行计划会描述这样的一个路线:打开表t上的索引idx1 ,找到带有“k”这个键的行然后返回行里面的a和b两列。
关于解析和编译,常见的问题在于SQL过于复杂或者不正确使用动态查询条件。从而使得解析过程异常困难并且导致后续的步骤主要是优化非常不准确。关于这部分的介绍可以看本人的系列文章(http://blog.csdn.net/dba_huangzj/article/details/49928527,“T-SQL动态查询”)。
在完成解析和编译之后,生成一个编译树,传到优化器中进行优化。
总结
解析和绑定是查询提交到SQL Server后的第一个操作,编译确保T-SQL查询是符合语法的,然后转换成原始的树结构(逻辑树),但是这个树结构依旧是表达语句的相对高级的表现。相对于源语句,逻辑树可以表达“从xx表中读取数据”、“进行inner join”这样的含义。但是在这个过程中逻辑树可以接收不同的名字。
绑定实际上是名称解析,用于对逻辑树进行检查,确保所有对象名都存在,所有关联的表及其列名都能在系统目录视图中存在。在绑定之后,就生成代数树并传入查询优化器中。