稀土掘金 稀土掘金

一文看懂SQL的执行顺序

1:为什么需要关注SQL的执行顺序?

看到这个问题,好多同学可能会说我能写出来正确的SQL,然后SQL能跑出结果就行了,为什么还要关心SQL的执行顺序呢?那么我们先回答这个问题,如果仅仅考虑能跑出结果就满意了,那确实没必要关注SQL的执行顺序。然而好多时候我们我们不是SQL不对,而是SQL跑了半天结果却没出来,机器没崩溃,可能你先崩溃了。所以,如果你想比别人快那么一点点的话,那就认真了解下SQL的执行顺序,这是我们写出漂亮SQL的关键。另外好多数据岗位的初级面试也会问到这个问题,不要以为这个问题很简单,实际情况好多人回答的都是你SQL语句从上到下的顺序。


2:先看一段经典的SQL

卖完关子我们来正式介绍SQL的执行顺序。以下面的SQL为例来说明具体的执行顺序


3:正向看SQL的执行顺序

SQL不长也不复杂,但是把我们前面提到的SQL的六脉神剑都用上了。我们把其中的关键字提取出来,

SELECT,DISTINCT, FROM, ON, JOIN,WHERE,GROUP BY,HAVING,ORDER BY,LIMIT。


执行顺序:


  1. FROM,为什么它是第一位呢?因为我们首先必须知道数据在哪?把数据取出来来以后才能做后续的操作。这里就是把student表和score表做笛卡尔积(笛卡尔积我们也有介绍过,具体参考SQL的六脉神剑),两个表笛卡尔积后生成临时虚拟表tmp1,当然如果是单表的话就直接把该表数据加载到内存即可。


  2. ON ,这里的ON 是JOIN后面的ON,ON的作用是根据JOIN的条件把临时表tmp中不符合st.id=sc.sid的记录给过滤掉,只保留满足条件的记录,这样数据量就会减少很多,经过这一步形成虚表tmp2。


  3. JOIN,这里JOIN的作用是根据JOIN的类型不同来对虚表tmp2做行的增减。具体来说,如果是LEFT (OUTER) JOIN就把上一步舍弃的左表的记录补回来,对应右表的数据用NULL填充;如果是RIGHT(OUTER) JOIN的话就把右表删除的记录补回来,同理FULL (OUTER) JOIN分别做类似的增加记录操作,但是(INNER) JOIN不会,所以这一步的操作主要针对的是OUTER JOIN,对应我们上面的SQL就是把student表中不等于score表中对应ID的记录给增补回来,这样操作之后形成虚表tmp3


  4. WHERE ,where是对增减后的虚表tmp做数据过滤操作,注意这一步是对关联后的所有数据即虚表tmp3做过滤操作,这一步不在区分是那种类型的JOIN了。针对我们上面的SQL,这一步的操作就是把tmp3中sex属性值不是’男‘的记录给剔除掉,只保留符合条件的记录,这一步操作后形成虚表tmp4,所以我们想要过滤掉最终结果的时候一般条件都是放到where里面的。


  5. GROUP BY,经过上面四步的操作,一般都可以取到符合我们要求的明细数据了,而group by 是对数据做聚合操作,必须放在正确的结果集后执行。试想,如果没有取到正确的结果就做聚合操作那么最终的结果一定也是不正确的。针对上面的SQL,按照学生的年龄分组后,形成虚表tmp5。


  6. HAVING,这一步也是过滤操作,只不过是对group by 聚合后的操作,所以它必然也就是在group by之后执行了,基本上到了这里我们的数据已经成型了,取出了满足了where条件的数据,然后按照group by 做了聚合,再根据having对结果集做了过滤,形成虚表tmp6。执行到这里算是已经成型了,再后面就是展示的问题了。针对上面的SQL,取出的是至少参见过一门考试的学生。


  7. SELECT, 这一步是把上面经过层层过滤后的数据按照指定的列给筛选出来,上面的SQL就是只把我们用到的列age,和聚合后的列num取出来,形成虚表tmp7,包含age列和新的列num。


  8. DISTINCT,这一步是对已经选择后的列,也即是虚表tmp7做指定列的去重操作。上面的SQL就是按照不同的学生ID做去重操作,形成虚表tmp8 。


  9. ORDER BY,order by的作用是按照指定的列进行排序,他也必须是在已经满足需要的结果集上排序,而且是已经选择(select)的列,如果我们select 中没有这一列那么是无法进行排序的。上面的SQL是按照学生的年龄从低到高排序,然后形成结果集tmp9。


  10. LIMIT,这是最后一步,对结果集做行上的处理,只不过这里是针对已经做完各种操作后的结果集做限制输出,所以它是放在最后执行,其实对整个执行过程而言没要减少复杂度,再看上面的SQL,取出来的是排序后的前100条记录,这就是最终的结果集tmp10,然后再把这个结果集输出出来。




4:逆向看SQL的执行顺序

上面十步就是一个典型SQL的执行过程,下面我们根据最终的结果来反推这整个执行过程帮助大家更好的记忆。


我们最终的需求是取出所有至少参加过一门考试的男生,按照年龄分组后正序排序的一组结果。那么由此倒推:


  1. 我们最后需要一个排序后的结果集,从中取出前100条,这是limit。


  2. 取前100条之前需要排序,这是order by。


  3. 排序执之前需要有结果列,这正常就是select,但是有些列不能直接统计,可能还需要一个去重操作,所以在select 之前还可能有distinct。


  4. 在select 之前我们需要把不满足条件的结果给剔除掉,所以如果是简单的明细数据,这一步之上就应该是where操作,但是如果是对聚合后的结果做过滤就需要在这之前有having,而having是对聚合结果做过滤,那么它之前必然就是group by了。


  5. 无论是对数据明细做过滤还是对聚合后的数据做过滤我们都依赖一个大的数据集,所以过滤之前要有join的操作,把多表先整合成一个大的数据集,供后面使用。


  6. 数据集从何而来的呢,这就是from的作用,所以from必须是第一位的,用来寻找数据。



这样一正一反是不是更加清晰明了?



5:一个SQL优化的实例

前面我们说了了解了SQL的执行顺序对于我们优化SQL有很大的帮助,下面就给大家举一个例子:


两条SQL的结果是一致的,在数据量不是很大的情况也执行效果差不多,但是如果是一个亿级的订单表和一个千万级的用户表关联的时候,B的效果要明显好于A的效果,因为根据SQL的执行顺序,B中,先在子查询中对需要join的两个表做了过滤,这样再join数据量就小了很多,而A中先join后过滤,开始的时候数据量很大,会影响执行的效果。怎么样,SQL的执行顺序还是很有用吧。


两个鬼故事网站起名字品牌起名商标命名大全鼠宝宝起名免费取名字网上宝宝能起名宁起名大全f1中国大奖赛穿书后我嫁给了残疾暴君暗夜使者名字男孩姓包取名起名大全五行查询起名女孩起名字论语阿凡达电影网宋代足球小子台湾版的中国地图火影羁绊4.33注册商标名字怎么起网名起什么好听昵称世纪华联超市加盟新荣村客运站男宝宝起名网广告公司起名如何起送你的独白农资市场起名用海取名起名大全起名打分周易通信公司起名字大全科兴疫苗第三针数据旬阳县城关一小建材建材公司起名的lol 起名字少年生前被连续抽血16次?多部门介入两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”淀粉肠小王子日销售额涨超10倍高中生被打伤下体休学 邯郸通报单亲妈妈陷入热恋 14岁儿子报警何赛飞追着代拍打雅江山火三名扑火人员牺牲系谣言张家界的山上“长”满了韩国人?男孩8年未见母亲被告知被遗忘中国拥有亿元资产的家庭达13.3万户19岁小伙救下5人后溺亡 多方发声315晚会后胖东来又人满为患了张立群任西安交通大学校长“重生之我在北大当嫡校长”男子被猫抓伤后确诊“猫抓病”测试车高速逃费 小米:已补缴周杰伦一审败诉网易网友洛杉矶偶遇贾玲今日春分倪萍分享减重40斤方法七年后宇文玥被薅头发捞上岸许家印被限制高消费萧美琴窜访捷克 外交部回应联合利华开始重组专访95后高颜值猪保姆胖东来员工每周单休无小长假男子被流浪猫绊倒 投喂者赔24万小米汽车超级工厂正式揭幕黑马情侣提车了西双版纳热带植物园回应蜉蝣大爆发当地回应沈阳致3死车祸车主疑毒驾恒大被罚41.75亿到底怎么缴妈妈回应孩子在校撞护栏坠楼外国人感慨凌晨的中国很安全杨倩无缘巴黎奥运校方回应护栏损坏小学生课间坠楼房客欠租失踪 房东直发愁专家建议不必谈骨泥色变王树国卸任西安交大校长 师生送别手机成瘾是影响睡眠质量重要因素国产伟哥去年销售近13亿阿根廷将发行1万与2万面值的纸币兔狲“狲大娘”因病死亡遭遇山火的松茸之乡“开封王婆”爆火:促成四五十对奥巴马现身唐宁街 黑色着装引猜测考生莫言也上北大硕士复试名单了德国打算提及普京时仅用姓名天水麻辣烫把捣辣椒大爷累坏了

两个鬼故事 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化