加入收藏 | 设为首页 | 会员中心 | 我要投稿 核心网 (https://www.hxwgxz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

Apache Flink 漫谈系列 - JOIN 算子

发布时间:2018-11-20 20:07:11 所属栏目:教程 来源:孙金城
导读:聊什么 在《Apache Flink 漫谈系列 - SQL概览》中我们介绍了JOIN算子的语义和基本的使用方式,介绍过程中大家发现Apache Flink在语法语义上是遵循ANSI-SQL标准的,那么再深思一下传统数据库为啥需要有JOIN算子呢?在实现原理上面Apache Flink内部实现和传统

上面的查询过程符合语义,但是如果在filter条件能过滤很多数据的时候,先进行数据的过滤,在进行内联接会获取更好的性能,比如我们手工写一下:

  1. mysql> SELECT 
  2.     ->   no, name , score 
  3.     -> FROM student stu JOIN ( SELECT s_no, score FROM score s WHERE s.score >80) as sc ON no = s_no; 
  4. +------+-------+-------+ 
  5. | no   | name  | score | 
  6. +------+-------+-------+ 
  7. | S001 | Sunny |    98 | 
  8. | S003 | Kevin |    88 | 
  9. +------+-------+-------+ 
  10. 2 rows in set (0.00 sec) 

上面写法语义和第一种写法语义一致,得到相同的查询结果,上面查询过程是:

  • 第一步:执行过滤子查询
    1. mysql> SELECT s_no, score FROM score s WHERE s.score >80; 
    2. +------+-------+ 
    3. | s_no | score | 
    4. +------+-------+ 
    5. | S001 |    98 | 
    6. | S003 |    88 | 
    7. +------+-------+ 
    8. 2 rows in set (0.00 sec) 
  • 第二步:执行内连接
    1. -> ON no = s_no; 
    2. +------+-------+-------+ 
    3. | no   | name  | score | 
    4. +------+-------+-------+ 
    5. | S001 | Sunny |    98 | 
    6. | S003 | Kevin |    88 | 
    7. +------+-------+-------+ 
    8. 2 rows in set (0.00 sec) 

如上两种写法在语义上一致,但查询性能在数量很大的情况下会有很大差距。上面为了和大家演示相同的查询语义,可以有不同的查询方式,不同的执行计划。实际上数据库本身的优化器会自动进行查询优化,在内联接中ON的联接条件和WHERE的过滤条件具有相同的优先级,,具体的执行顺序可以由数据库的优化器根据性能消耗决定。也就是说物理执行计划可以先执行过滤条件进行查询优化,如果细心的读者可能发现,在第二个写法中,子查询我们不但有行的过滤,也进行了列的裁剪(去除了对查询结果没有用的c_no列),这两个变化实际上对应了数据库中两个优化规则:

  • filter push down
  • project push down

如上优化规则以filter push down 为例,示意优化器对执行plan的优化变动:

Apache Flink 漫谈系列 - JOIN 算子

3. LEFT OUTER JOIN

左外联接语义是返回左表所有行,右表不存在补NULL,为了演示作用,我们查询没有参加考试的所有学生的成绩单:

  1. mysql> SELECT 
  2.     ->   no, name , s.c_no, s.score 
  3.     -> FROM student stu LEFT JOIN score s ON sstu.no = s.s_no 
  4.     -> WHERE s.score is NULL; 
  5. +------+------+------+-------+ 
  6. | no   | name | c_no | score | 
  7. +------+------+------+-------+ 
  8. | S002 | Tom  | NULL |  NULL | 
  9. +------+------+------+-------+ 
  10. 1 row in set (0.00 sec) 

上面查询的执行逻辑上也是分成两步:

  • 第一步:左外联接查询
    1. mysql> SELECT 
    2.     ->   no, name , s.c_no, s.score 
    3.     -> FROM student stu LEFT JOIN score s ON sstu.no = s.s_no; 
    4. +------+-------+------+-------+ 
    5. | no   | name  | c_no | score | 
    6. +------+-------+------+-------+ 
    7. | S001 | Sunny | C01  |    80 | 
    8. | S001 | Sunny | C02  |    98 | 
    9. | S001 | Sunny | C03  |    76 | 
    10. | S002 | Tom   | NULL |  NULL | -- 右表不存在的补NULL 
    11. | S003 | Kevin | C01  |    78 | 
    12. | S003 | Kevin | C02  |    88 | 
    13. | S003 | Kevin | C03  |    68 | 
    14. +------+-------+------+-------+ 
    15. 7 rows in set (0.00 sec) 
  • 第二步:过滤查询
    1. mysql> SELECT  
    2.     ->   no, name , s.c_no, s.score 
    3.     -> FROM student stu LEFT JOIN score s ON sstu.no = s.s_no 
    4.     -> WHERE s.score is NULL; 
    5. +------+------+------+-------+ 
    6. | no   | name | c_no | score | 
    7. +------+------+------+-------+ 
    8. | S002 | Tom  | NULL |  NULL | 
    9. +------+------+------+-------+ 
    10. 1 row in set (0.00 sec) 

(编辑:核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读