SQ中查询底层运行原理是什么

53次阅读
没有评论

共计 3255 个字符,预计需要花费 9 分钟才能阅读完成。

自动写代码机器人,免费开通

丸趣 TV 小编给大家分享一下 SQ 中查询底层运行原理是什么,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

数据准备

本文旨在说明 SQL 查询的执行过程,不会涉及太复杂的 SQL 操作,主要涉及两张表:citizen 和 city , 具体数据如下所示:

CREATE TABLE citizen ( 
 name CHAR ( 20 ), 
 city_id INT ( 10 ) 

 city_id INT ( 10 ),   city_name CHAR ( 20 )  INSERT INTO city VALUES  ( 1,  上海  ),  ( 2,  北京  ),  ( 3,  杭州  );     INSERT INTO citizen VALUES (tom ,3), (jack ,2), (robin ,1), (jasper ,3), (kevin ,1), (rachel ,2), (trump ,3), (lilei ,1), (hanmeiei ,1);

查询执行顺序

本文所涉及的查询语句如下,主要是 citizen 表与 city 表进行 join,然后筛掉 city_name != 上海 的数据,接着按照 city_name 进行分组,统计每个城市总人数大于 2 的城市,具体如下:

查询语句

SELECT 
 city.city_name AS  City ,
 COUNT(*) AS  citizen_cnt
FROM citizen
 JOIN city ON citizen.city_id = city.city_id 
WHERE city.city_name !=  上海 
GROUP BY city.city_name
HAVING COUNT(*)  = 2
ORDER BY city.city_name ASC
LIMIT 2

执行步骤

上面 SQL 查询语句的书写书序是:

SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ...

但是执行顺序并不是这样,具体的执行顺序如下步骤所示:

1. 获取数据 (From, Join)

2. 过滤数据 (Where)

3. 分组 (Group by)

4. 分组过滤 (Having)

5. 返回查询字段 (Select)

6. 排序与分页 (Order by Limit / Offset)

尖叫提示:本文旨在说明通用的 SQL 执行底层原理,对于其优化技术不做考虑,比如谓词下推、投影下推等等。

执行的底层原理

其实上面所说的 SQL 执行顺序就是所谓的底层原理,当我们在执行 SELECT 语句时,每个步骤都会产生一张 虚拟表 (virtual table),在执行下一步骤时,会将该虚拟表作为输入。指的注意的是,这些过程是对用户透明的。

你可以注意到,SELECT 是先从 FROM 这一步开始执行的。在这个阶段,如果是多张表进行 JOIN,还会经历下面的几个步骤:

获取数据 (From, Join)

首先会通过 CROSS JOIN 求笛卡尔积,相当于得到虚拟表 vt1-1;

接着通过 ON 条件进行筛选,虚拟表 vt1-1 作为输入,输出虚拟表 vt1-2;

添加外部行。我们使用的是左连接、右链接或者全连接,就会涉及到外部行,也就是在虚拟表 vt1-2 的基础上增加外部行,得到虚拟表 vt1-3

过滤数据 (Where)

经过上面的步骤,我们得到了一张最终的虚拟表 vt1,在此表之上作用 where 过滤,通过筛选条件过滤掉不满足条件的数据,从而得到虚拟表 vt2。

分组 (Group by)

经过 where 过滤操作之后,得到 vt2。接下来进行 GROUP BY 操作,得到中间的虚拟表 vt3。

分组过滤 (Having)

在虚拟表 vt3 的基础之上,使用 having 过滤掉不满足条件的聚合数据,得到 vt4。

返回查询字段 (Select)

当我们完成了条件筛选部分之后,就可以筛选表中提取的字段,也就是进入到 SELECT 和 DISTINCT 阶段。首先在 SELECT 阶段会提取目标字段,然后在 DISTINCT 阶段过滤掉重复的行,分别得到中间的虚拟表 vt5-1 和 vt5-2。

排序与分页 (Order by Limit / Offset)

当我们提取了想要的字段数据之后,就可以按照指定的字段进行排序,也就是 ORDER BY 阶段,得到虚拟表 vt6。最后在 vt6 的基础上,取出指定行的记录,也就是 LIMIT 阶段,得到最终的结果,对应的是虚拟表 vt7

详细执行步骤分析

Step 1: 获取数据 (From, Join)

FROM citizen
JOIN city

该过程的第一步是执行 From 子句中的语句,然后执行 Join 子句。这些操作的结果是得到两个表的笛卡尔积。

namecity_idcity_idcity_nametom31 上海 tom32 北京 tom33 杭州 jack21 上海 jack22 北京 jack23 杭州 robin11 上海 robin12 北京 robin13 杭州 jasper31 上海 jasper32 北京 jasper33 杭州 kevin11 上海 kevin12 北京 kevin13 杭州 rachel21 上海 rachel22 北京 rachel23 杭州 trump31 上海 trump32 北京 trump33 杭州 lilei11 上海 lilei12 北京 lilei13 杭州 hanmeiei11 上海 hanmeiei12 北京 hanmeiei13 杭州

在 FROM 和 JOIN 执行结束之后,会按照 JOIN 的 ON 条件,筛选所需要的行

ON citizen.city_id = city.city_id

namecity_idcity_idcity_nametom33 杭州 jack22 北京 robin11 上海 jasper33 杭州 kevin11 上海 rachel22 北京 trump33 杭州 lilei11 上海 hanmeiei11 上海

Step 2: 过滤数据 (Where)

获得满足条件的行后,将传递给 Where 子句。这将使用条件表达式评估每一行。如果行的计算结果不为 true,则会将其从集合中删除。

WHERE city.city_name !=  上海 

namecity_idcity_idcity_nametom33 杭州 jack22 北京 jasper33 杭州 rachel22 北京 trump33 杭州

Step 3: 分组 (Group by)

下一步是执行 Group by 子句,它将具有相同值的行分为一组。此后,将按组对所有 Select 表达式进行评估,而不是按行进行评估。

GROUP BY city.city_name

GROUP_CONCAT(citizen. name )city_idcity_namejack,rachel2 北京 tom,jasper,trump3 杭州

Step 4: 分组过滤 (Having)

对分组后的数据使用 Having 子句所包含的谓词进行过滤

HAVING COUNT(*)  = 2

Step 5: 返回查询字段 (Select)

在此步骤中,处理器将评估查询结果将要打印的内容,以及是否有一些函数要对数据运行,例如 Distinct,Max,Sqrt,Date,Lower 等等。本案例中,SELECT 子句只会打印城市名称和其对应分组的 count(*) 值,并使用标识符“City”作为 city_name 列的别名。

SELECT 
 city.city_name AS  City ,
 COUNT(*) AS  citizen_cnt

citycitizen_cnt 北京 2 杭州 3

Step 6: 排序与分页 (Order by Limit / Offset)

查询的最后处理步骤涉及结果集的排序与输出大小。在我们的示例中,按照字母顺序升序排列,并输出两条数据结果。

ORDER BY city.city_name ASC
LIMIT 2

citycitizen_cnt 北京 2 杭州 3

以上是“SQ 中查询底层运行原理是什么”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注丸趣 TV 行业资讯频道!

向 AI 问一下细节

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-12-04发表,共计3255字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)