Database Inside 系列 ——SQL 是如何执行的

简介: Database Inside 系列 ——SQL 是如何执行的

Database Inside 是一个新开的小系列,旨在为初学者建立一个对数据库的的基本观感,或者说直觉。本系列定位,求短不求全、用意不用力。前因后果、内涵外延,点到即止。文末会给些许参考,若不尽兴,可自行探求。

SQL 的三维侧写

SQL 起源于上世纪七十年代的 IBM R 系统,是一个针对关系型数据库的声明查询语言。一句话引出三个点:

1. 关系型(relational):基于关系代数理论的一种数据建模方式,其他的建模方式如文档数据库、图数据库等。以 SQL 表的方式来理解,可以将任何数据集抽象为一张二维表,每一个元组(tuple),每个元组有多个属性;将对数据集的查询抽象为一组运算符的组合,也即二维表的一组变换。常见的运算符:

image.png

关系表的变换

  1. 选择 (σ):针对单张二维表,选择其中一些行;对应 SQL 中 where 子句
  2. 投影 (π):针对单张二维表,选择其中某几列;对应 SQL 中 select xx 子句
  3. 自然连接 (⋈):针对两张二维表,按某一列上等值进行合并;对应 SQL 中 join 子句

2. 声明式(declarative):与命令式(imperative)相对,可类比编程中的接口。侧重于描述而非实现。举个例子感受一下:

  1. 声明式:“找出教三今天的空闲教室”
  2. 命令式:“1. 找出教三所有教室 2. 对于每间教室查询课表看其是否空闲 3. 如果空闲则加入结果集”

3. 查询语言(Query):顾名思义,这是一门专门用来做诸如“找教室”一类的对满足条件的数据进行查询的语言。虽然他是图灵完备的,但一般不用于像通用编程语言 C++ 等来编写复杂软件。

SQL 执行过程

image.png

                                    CMU 15445 课程图

SQL 也是一门语言,因此其执行过程和编译器前端类似,参考上图(来自 cmu 15-445)可粗分为数个步骤:

  1. 解析(Parsing):将适合人阅读的 SQL 语句进行分词(token),并进行基本语法检查。然后基于关系代数,构建成抽象语法树(AST,Abstract Syntax Tree)。其中叶子节点为表,中间节点为运算符。
  2. 校验(Validating):检查所插入数据格式是否满足之前所定义的模式。举个例子,学生表定义了学号、姓名、课程三列,则插入的数据每一行不能多于三个属性。
  3. 计划(Planning):使用模式信息,将语法树中元素(各种有意义的名称)转成内部表示(各种 无意义且不重复 id),生成逻辑计划。
  4. 优化(Optimization):逻辑计划由多个数据变换操作构成,我们可以基于关系代数中算子的一些性质(比如交换性、结合性),调整变换顺序和组合,使得查询所耗费资源(包括计算、存储和网络带宽等)最小,最后生成物理执行计划,常包括基于规则和基于代价的两种方式。
  5. 执行(Execution):将优化过后的执行计划(一般仍是树形)进行执行。包括从外存捞数据到内存和在内存中对数据做各种变换。不管数据在外存表现为什么形式,捞到内存后可以理解为一张前面提到的二维表,然后按树结构施加各种算子,进行计算。

有时候校验阶段也被归入解析范畴,有时候执行阶段中的表达式求值会单拎出来说,但总的职责就这几个,排列顺序基本确定,只是划分可能有出入。

之后对于每个阶段,会分别出一篇小文。

参考

  1. https://15445.courses.cs.cmu.edu/fall2022/notes/02-modernsql.pdf
  2. https://15445.courses.cs.cmu.edu/fall2022/notes/14-optimization.pdf
  3. Database System Concepts, Chapter 15 Query Processing and Chapter 16 Query Optimization


相关文章
|
12天前
|
SQL 存储 关系型数据库
SQL `CREATE DATABASE` 语法
【11月更文挑战第10天】
33 3
|
5月前
|
SQL 关系型数据库 MySQL
怎么通过第三方库实现标准库`database/sql`的驱动注入?
在Go语言中,数据库驱动通过注入`database/sql`标准库实现,允许统一接口操作不同数据库。本文聚焦于`github.com/go-sql-driver/mysql`如何实现MySQL驱动。`database/sql`提供通用接口和驱动注册机制,全局变量管理驱动注册,`Register`函数负责添加驱动,而MySQL驱动在`init`函数中注册自身。通过这个机制,开发者能以一致的方式处理多种数据库。
|
2月前
|
关系型数据库 MySQL Java
flywa报错java.sql.SQLSyntaxErrorException: Unknown database ‘flyway‘
flywa报错java.sql.SQLSyntaxErrorException: Unknown database ‘flyway‘
35 1
|
4月前
|
SQL 数据库
SQL CREATE DATABASE 语句
【7月更文挑战第18天】SQL CREATE DATABASE 语句。
141 1
|
5月前
|
SQL 监控 NoSQL
db.oplog.rs.find({"ns": "your_database_name.your_collection_name", "o": {$exists: true}}).sort({$natural: -1}).limit(1) 这个SQL什么意思
【6月更文挑战第29天】db.oplog.rs.find({"ns": "your_database_name.your_collection_name", "o": {$exists: true}}).sort({$natural: -1}).limit(1) 这个SQL什么意思
45 8
|
5月前
|
SQL 数据库
SQL CREATE DATABASE 语句
SQL CREATE DATABASE 语句
68 4
|
5月前
|
SQL 数据库
SQL CREATE DATABASE 语句
SQL CREATE DATABASE 语句
47 2
|
6月前
|
SQL 数据库
导入 sql 文件,如果发生 ERROR 1046 (3D000) no database selected 错误
导入 sql 文件,如果发生 ERROR 1046 (3D000) no database selected 错误
99 0
|
关系型数据库 MySQL 数据库
java.sql.SQLException: Connections could not be acquired from the underlying database!
java.sql.SQLException: Connections could not be acquired from the underlying database!
406 0