我们看看 TiDB 一段代码的实现 --- 左外连接(Left Out Join)的消除;

select 的优化一般是这样的过程:

在逻辑执行计划的优化阶段, 会有很多关系代数的规则, 需要将逻辑执行计划(LogicalPlan)树应用到各个规则中, 尝试进行优化改写;

我们看看其中的一条优化规则: outerJoinEliminator

TiDB作为优秀的开源项目, 代码的注释也非常优秀, 里面提到了满足这些条件的 Left Outer Join 可以消除右表;

// tryToEliminateOuterJoin will eliminate outer join plan base on the following rules
// 1. outer join elimination: For example left outer join, if the parent only use the
// columns from left table and the join key of right table(the inner table) is a unique
// key of the right table. the left outer join can be eliminated.
// 2. outer join elimination with duplicate agnostic aggregate functions: For example left outer join.
// If the parent only use the columns from left table with 'distinct' label. The left outer join can
// be eliminated.

我们这里只讨论第一种情况, 第二种情况请您自行查看源码;

我们构造满足第一种情况的查询:

左表:

  t1(
    id int primary key not null auto_increment,
    a int,
    b int
  );

右表:

  t2(
    id int primary key not null auto_increment,
    a int,
    b int
  );

查询语句:

  select t1.id, t1.a from t1 left join t2 on t1.id = t2.id;

我们看看优化规则之前的逻辑执行计划:

这个执行计划是这样的:

  顶层的算子是投影(Projection)操作, 取 t1.id 和 t1.a 这两列;

  接下来是 连接(Join) 操作, 类型是: LeftOuterJoin;

  接下来左边是 OuterPlan, 左表; 右边是 InnerPlan, 右表;

  左边的算子是扫 t1 的数据, 右边的算子是扫 t2 表的数据;

  底层的算子将数据返回给上层的算子, 来完成计划的执行;

     注, 这种数据自底向上的流动方式有点像火山喷发, 所以这种执行模型叫做火山模型(Volcano);

主要代码逻辑在这里:

  outerJoinEliminator::doOptimize

    这是一个递归的操作, 不断的获取 parentCols, 并对 LeftOuterJoin 或者 RightOuterJoin 尝试进行消除;

    如果是LeftOuterJoin , 尝试消除右表, 如果是RightOuterJoin, 尝试消除左表;

因为我们这里只有 Projection算子 和 LeftOuterJoin算子, 所以代码调用逻辑基本是这样的:

  * 获取Projection的列

  * 对下面的LeftOuterJoin进行判断

    * 获取左表的列: outerPlan.Schema().Columns

    * 判断上层 Projection 用到的列是否全部来自左表: o.isColsAllFromOuterTable(parentCols, outerUniqueIDs)

    * 获取 Join 连接的列: innerJoinKeys := o.extractInnerJoinKeys(p, innerChildIdx); 这即是右表的 t2.id

    * 判断连接的列是否被包含在右表的主键: o.isInnerJoinKeysContainUniqueKey(innerPlan, innerJoinKeys)

    * 满足条件, 将 LeftOutJoin 替换掉;

我们展示一下这个转换:

上图中灰色的执行计划会被消除掉;

变成了下面的执行计划:

最终, 上面给出的sql 的例子等价于下面的语句:

  select t1.id, t1.a from t1;

有兴趣的读者可以看看其他的满足条件的左外连接消除的逻辑, 这里就不讲了;

逻辑优化的过程一般被叫做RBO(rule based optimization);

  逻辑规则的优化是基于关系代数的等价推导和证明;

  大部分数据库(例如mysql, Oracle, SQLServer)的逻辑优化规则都类似, 可以互相参考;

物理优化的过程一般被叫做CBO(cost based optimization);

  不同的数据库的物理优化规则不一定是一样的, 这个可能根据数据和索引的存放特点来进行针对性的处理;

简单聊聊TiDB中sql优化的一个规则---左连接消除(Left Out Join Elimination)的更多相关文章

  1. sql优化实例(用左连接)

    改为 也就是说用左连接代替where条件,这样的话效率会提高很多.

  2. 简单聊聊java中的final关键字

    简单聊聊java中的final关键字 日常代码中,final关键字也算常用的.其主要应用在三个方面: 1)修饰类(暂时见过,但是还没用过); 2)修饰方法(见过,没写过); 3)修饰数据. 那么,我们 ...

  3. 简单聊聊CSS中的3D技术之“立方体”

    简单聊聊CSS中的3D技术之“立方体” 大家好,我是今天的男一号,我叫小博主. 今天来聊一下我在前端“逆战班”学习中遇到的颇为有趣的3D知识.前端学习3周,见识稀疏,在下面的分享中如有不对的地方请大家 ...

  4. [转帖]关于Java中SQL语句的拼接规则

    关于Java中SQL语句的拼接规则 自学demo 的时候遇到的问题 结果应该是 '"+e.getName()+"' 注意 一共有三组标点符号 (除去 方法函数后面的括号) 实现目标 ...

  5. oracle中sql优化

    问题描述:刚开始做项目的时候没啥感觉,只用能出来结果,sql随便写,但是后来用户的数据量达到几万条是,在访问系统,发现很多功能加载都很慢,有的页面一个简单的关联 查询居然要花费30多秒,实在是不能忍, ...

  6. oracle11g中SQL优化(SQL TUNING)新特性之Adaptive Cursor Sharing (ACS)

    1.   ACS简介 Oracle Database 11g提供了Adaptive Cursor Sharing (ACS)功能,以克服以往不该共享的游标被共享的可能性.ACS使用两个新指标:sens ...

  7. Java并发(10)- 简单聊聊JDK中的七大阻塞队列

    引言 JDK中除了上文提到的各种并发容器,还提供了丰富的阻塞队列.阻塞队列统一实现了BlockingQueue接口,BlockingQueue接口在java.util包Queue接口的基础上提供了pu ...

  8. 对oracle中SQL优化的理解

    Oracle数据库里SQL优化的终极目标就是要缩短目标SQL语句的执行时间.要达到上述目的,我们通常只有如下三种方法可以选择:1.降低目标SQL语句的资源消耗.2.并行执行目标SQL语句.3.平衡系统 ...

  9. SQL优化之列裁剪和投影消除

    列裁剪 对于没用到的列,则没有必要读取它们的数据去浪费无谓的IO 比如我们有一张表table1,它含有四列数据(a,b,c,d).当我们执行查询select a from table1 where c ...

随机推荐

  1. PAT(B) 1069 微博转发抽奖(Java)

    题目链接:1069 微博转发抽奖 (20 point(s)) 题目描述 小明 PAT 考了满分,高兴之余决定发起微博转发抽奖活动,从转发的网友中按顺序每隔 N 个人就发出一个红包.请你编写程序帮助他确 ...

  2. 如何加入 Skype for Business 会议?

    参加一个线上培训,收到了Skype的参会地址,是这个样子的 然后就是一脸懵逼的不知道怎么参加会议了.找了半天终于在同事的帮助下参加成功. 我的参加方法:在Window上用Skype for Busin ...

  3. 此方法显式使用的 CAS 策略已被 .NET Framework 弃用。若要出于兼容性原因而启用 CAS 策略,请使用 NetFx40_LegacySecurityPolicy 配置开关

    使用DEV8.3winform控件,框架从.net2.0升级到4.0后,程序报错,调用的目标异常. 此方法显式使用的 CAS 策略已被 .NET Framework 弃用.若要出于兼容性原因而启用 C ...

  4. ExcelReport.cs Excel操作类、实例源码下载

    标题一.告别ASP.NET操作EXCEL的烦恼标题二.ASP.NET操作EXCEL 合并单元格 大全... cnblogs/hanzhaoxin/韩兆新的博客园ExcelReport第一篇:使用Exc ...

  5. 转:common.js 常用js公共函数库

    转自其他博主,自己开发备用 var h = {}; h.get = function (url, data, ok, error) { $.ajax({ url: url, data: data, d ...

  6. TypeScript入门一:配置TS工作环境

    配置手动编译TS文件工作环境 配置webpack自动化打包编译工作环境(后面补充) 一.TypeScript入门学习引言 进入主题之前,首先说明这个系列的博客是我刚刚接触TypeScript的学习笔记 ...

  7. 从SAP社区上的一篇博客开始,聊聊SAP产品命名背后的那份情怀

    最近Jerry在SAP社区上看到一篇博客:It's Steampunk now. 博客原文:https://blogs.sap.com/2019/08/20/its-steampunk-now/ 什么 ...

  8. Java原子操作类汇总(2)

    当程序更新一个变量时,如果是多线程同时更新这个变量,可能得到的结果与期望值不同.比如:有一个变量i,A线程执行i+1,B线程也执行i+1,经过两个线程的操作后,变量i的值可能不是期望的3,而是2.这是 ...

  9. 一个让Java事半功倍的反射库

    在Java和Android中,我们常常会使用反射来达到一些兼容的目的.Java原生提供的反射很是麻烦,使用起来很是不方便.比如我们想要调UserManager的静态方法get,使用原生的实现如下 tr ...

  10. c# 定制处理未处理异常