SQ中查询底层运行原理是什么
小编给大家分享一下SQ中查询底层运行原理是什么,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!
数据准备
本文旨在说明SQL查询的执行过程,不会涉及太复杂的SQL操作,主要涉及两张表: citizen 和 city ,具体数据如下所示:
CREATETABLEcitizen(nameCHAR(20),city_idINT(10));CREATETABLEcity(city_idINT(10),city_nameCHAR(20));INSERTINTOcityVALUES(1,"上海"),(2,"北京"),(3,"杭州");INSERTINTOcitizenVALUES("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的城市,具体如下:
查询语句
SELECTcity.city_nameAS"City",COUNT(*)AS"citizen_cnt"FROMcitizenJOINcityONcitizen.city_id=city.city_idWHEREcity.city_name!='上海'GROUPBYcity.city_nameHAVINGCOUNT(*)>=2ORDERBYcity.city_nameASCLIMIT2
执行步骤
上面SQL查询语句的书写书序是:
SELECT...FROM...WHERE...GROUPBY...HAVING...ORDERBY...
但是执行顺序并不是这样,具体的执行顺序如下步骤所示:
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 )
FROMcitizenJOINcity
该过程的第一步是执行From子句中的语句,然后执行Join子句。这些操作的结果是得到两个表的笛卡尔积。
在FROM和JOIN执行结束之后,会按照JOIN的ON条件,筛选所需要的行
ONcitizen.city_id=city.city_idname city_id city_id city_name tom33杭州jack22北京robin11上海jasper33杭州kevin11上海rachel22北京trump33杭州lilei11上海hanmeiei11上海
Step 2:过滤数据 ( Where )
获得满足条件的行后,将传递给Where子句。这将使用条件表达式评估每一行。如果行的计算结果不为true,则会将其从集合中删除。
WHEREcity.city_name!='上海'name city_id city_id city_name tom33杭州jack22北京jasper33杭州rachel22北京trump33杭州
Step 3:分组 ( Group by )
下一步是执行Group by子句,它将具有相同值的行分为一组。此后,将按组对所有Select表达式进行评估,而不是按行进行评估。
GROUPBYcity.city_nameGROUP_CONCAT(citizen.name) city_id city_name jack,rachel2北京tom,jasper,trump3杭州
Step 4:分组过滤 ( Having )
对分组后的数据使用Having子句所包含的谓词进行过滤
HAVINGCOUNT(*)>=2
Step 5:返回查询字段 ( Select )
在此步骤中,处理器将评估查询结果将要打印的内容,以及是否有一些函数要对数据运行,例如Distinct,Max,Sqrt,Date,Lower等等。本案例中,SELECT子句只会打印城市名称和其对应分组的count(*)值,并使用标识符“ City”作为city_name列的别名。
SELECTcity.city_nameAS"City",COUNT(*)AS"citizen_cnt"city citizen_cnt 北京2杭州3
Step 6:排序与分页 ( Order by & Limit / Offset )
查询的最后处理步骤涉及结果集的排序与输出大小。在我们的示例中,按照字母顺序升序排列,并输出两条数据结果。
ORDERBYcity.city_nameASCLIMIT2city citizen_cnt 北京2杭州3
以上是“SQ中查询底层运行原理是什么”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。