您的位置:首页 > 数据库

深入理解-SQL查询语句的执行流程

2019-01-12 10:56 375 查看

SQL查询语句的执行流程(以Oracle举例)

首先, 准备两张表
用户表user
角色表role

先来一个基本的查询语句

SELECT * FROM "user" u, "role" r WHERE u."rid"=r."rid" ORDER BY u."age" DESC

这时发生了什么呢
一共三个步骤

  1. 加载表
  2. 筛选数据
  3. 返回数据

那么按照这个流程, 解析一下上面的SQL语句的运行流程

  1. 匹配到SELECT关键字, 是查询语句, 寻找form
  2. 匹配到FROM关键字, 找到其后面的"user" u, “role” r 加载表到内存中
  3. 将FROM后面的所有表做笛卡尔积, 生成虚表VT1, 此时加载表执行完毕
  4. 匹配WHERE关键字, 执行 u.“rid” = r.“rid” 进行表的筛选, 生成虚表VT2
  5. 此时得到的VT2大致满足了我们的要求, 但还差一步, 数据处理
  6. 执行 ORDER BY u.“age” DESC 将VT2的数据进行排序, 生成VT3
  7. 返回VT3

此时, 我们就能拿到SQL语句预期拿到的数据了
这就是本条SQL产生的三条虚拟表的样子

==================== 华丽的分割线 ====================
如果上面的内容你能理解的话, 那么我们来详细谈谈 SQL三联

  1. 加载表

加载表是将一条查询语句中所需要的表加载进内存, 并按照连接方式生成虚拟表VT1

加载进内存很好理解, 就是把所有需要的表找到, 从磁盘加载进内存
但是可能有的同学想到了, 子查询中可以将查询语句的结果当做一张表给外部使用, 所以加载表也是可以加载其他SQL生成的虚拟表的

生成虚拟表, 这个有些难, 首先表之间要先进行表连接(隐式内连接, 内连接, 左联接, 右连接)
表连接要先做笛卡尔积(生成所有的可能), 在通过连接条件进行筛选, 过滤掉大部分无用数据, 生成虚拟表VT1

  1. 筛选数据

去掉不满足条件的, 留下符合的

这步是将加载表生成的VT1通过各种条件(例: u.“username” = ‘张三’) 进行筛选, 不满足条件的将被去除, 然后生成虚拟表VT2
处了用where进行筛选, 还可以用GROUP BY进行分组, 和使用HAVING进行分组筛选
分组后一张完整的虚拟表VT2将被按照分组字段分成n个小虚拟表, 这些小虚拟表组成一个虚拟表数组
然后进行分组筛选, 这会遍历虚拟表数组中的所有虚拟表进行筛选, 所以十分浪费资源, 同样的, 不满足条件的将被去除

  1. 返回数据

数据将变成你想要的模样

从筛选数据生成的虚拟表后虚拟表数组提取你想要的数据, 这并不会去除那些不符合要求的数据
这里有一个要求, 就是处理完成的数据一定要是一张完整的虚拟表, 不能是虚拟表数组,
这也就是为什么分组之后只能返回分组字段(因为其他字段可能有多条数据),
当然 ,也可以返回聚合函数(聚合函数将多条数据聚合成为一条)
在返回数据之前, 还可以使用排序或分页进行最后的数据处理, 然后按照返回的格式, 生成你想要的数据(比如只要名字和年龄), 无论如何, 最后返回的都只能是一张完整的虚表, 这张虚拟表还可以被其他SQL当做表加载使用, 也就是子查询

==================== 华丽的分割线 ====================
到这里SQL查询语句的执行流程就差不多了, 如果完全理解了这里, 你便能灵活使用SQL语句查询出想要的数据, 而不再拘泥于格式

但是Oracle还有函数处理及集合运算, 这部分有事怎么回事呢

敬请期待…

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: