SQL是如何在数据库中执行的

143 阅读3分钟

SQL 是如何在执行器中执行的?

数据库收到查询请求后,需要先解析 SQL 语句,把这一串文本解析成便于程序处理的结构化数据,这就是一个通用的语法解析过程。

转换后的结构化数据,就是一棵树,这个树的名字叫抽象语法树(AST,Abstract Syntax Tree)。

image.png

执行器解析这个 AST 之后,会生成一个逻辑执行计划。所谓的执行计划,可以简单理解为如何一步一步地执行查询和计算,最终得到执行结果的一个分步骤的计划。这个逻辑执行计划是这样的:

image.png

上面这个执行计划,很像我们编程语言的函数调用栈,外层的方法调用内层的方法。所以,要理解这个执行计划,得从内往外看。

  1. 最内层的 2 个 LogicalTableScan 的含义是,把 USERS 和 ORDERS 这两个表的数据都读出来。
  2. 然后拿这两个表所有数据做一个 LogicalJoin,JOIN 的条件就是第 0 列 (u.id) 等于第 6 列 (o.user_id)。
  3. 然后再执行一个 LogicalFilter 过滤器,过滤条件是第 0 列 (u.id) 大于 50。
  4. 最后,做一个 LogicalProject 投影,只保留第 0(user_id)、1(user_name)、5(order_id) 三列。这里“投影 (Project)”的意思是,把不需要的列过滤掉。

优化的总体思路是,在执行计划中,尽早地减少必须处理的数据量。也就是说,尽量在执行计划的最内层减少需要处理的数据量。

SQL 是如何在存储引擎中执行的?

存储引擎主要功能就是把逻辑的表行列,用合适的物理存储结构保存到文件中。 MYSQL默认的存储引擎是 InnoDB,在 InnoDB 中,数据表的物理存储结构是以主键为关键字的 B+ 树,每一行数据直接就保存在 B+ 树的叶子节点上。

image.png

优化后的逻辑执行计划将会被转换成物理执行计划,物理执行计划是和数据的物理存储结构相关的。还是用 InnoDB 来举例,直接将逻辑执行计划转换为物理执行计划:

image.png

最终,按照优化后的物理执行计划,一步一步地去执行查找和计算,就可以得到 SQL 的查询结果了。

我们知道了 InnoDB 的索引实现后,就很容易明白为什么主键不能太长,因为表的每个索引保存的都是主键的值,过长的主键会导致每一个索引都很大。再比如,我们了解了执行计划的优化过程后,就很容易理解,有的时候明明有索引却不能命中的原因是,数据库在对物理执行计划优化的时候,评估发现不走索引,直接全表扫描是更优的选择。


此文章为3月Day10学习笔记,内容来源于极客时间《后端存储实战课》