列裁剪

  对于没用到的列,则没有必要读取它们的数据去浪费无谓的IO

  比如我们有一张表table1,它含有四列数据(a,b,c,d)。当我们执行查询select a from table1 where c 10时,我们可以清晰的看到,table1中只有a,c两列被用到了。分别是Selection算子用到c列和Projection算子用到a列。那么DataSource读取数据时,b,d两列则不需要读取,可以裁剪掉。

  那么都有哪些算子与列有关系呢?综合我们多年来使用SQL的经验来看,Selection(Where 条件)、Projection(搜索的列)、Sort(排序列)、Join(等值连接)、Aggregation(Group By及相关聚合操作)等。

  列裁剪的算法就是自顶向下的把算子过一遍,某个节点需要用到的列就等于它自己需要用到的列加上它的父节点所需要用到的列。这样得到整个SQL语句所涉及到的列,从而再读取数据时只读取需要的列即可。

  列裁剪通过只读取需要的数据减少IO操作来达到优化的目的

  投影消除

  投影消除是把不必要的Projection给消除掉

  那么问题来了,什么情况下,投影算子是可以被消除的呢?

  如何Projection算子需要投影的列跟子节点的输出列一样,那么这个投影就是一个废操作,可以被消除掉。比如说:select a,b from table1 如果再表table1中刚好只有a,b两列,也就是DataSource的输出和Projection需要投影的列一样,那么这时候就没必要在TableScan之后再做一次Projection操作了。

  如果Projection的子节点还是Projection的话,那么子节点的Projection就没有意义了,可以干掉。如:select a from (select a,b,c from table2) 这条语句里面有两个Projection,分别是最上层的Projection(a)和它的子节点Projection(a,b,c)。那么Projection(a,b,c)这个节点就是废操作,可以被消除掉。

  Aggregation在某种意义上也属于投影操作,因为从这个节点出来的都是列的概念,比如Max(a)、Min(b)等。因此在Aggregation-Projection的过程中,这个Projection也是可以被消除掉的。

  所以说,一个节点是否可以被消除,一方面是由它的父节点告诉它,它是否是一个冗余的Projection操作。另一方面是它自己和孩子节点做比较,看自身是否可以被消除。

  public void eliminate(Plan plan, boolean canEliminate) {

  //如果plan为Projection则判断是否需要被消除

  if (plan is Projection) {

  //如果父节点调用时指定canEliminate为true,则进行消除操作

  if (canEliminate) {

  doEliminate(plan);

  }

  //如果plan的输出和子节点的输出一样则消除plan

  if (checkPlanOutEqualsNext(plan)) {

  doEliminate(plan);

  }

  }

  //递归调用,遍历子节点

  eliminate(plan.next(), checkPlanNextCanEliminate(plan));

  }

  最大最小消除

  最大最小消除严格上说不是标准逻辑优化里面需要做的事情

  举个栗子:

  语句1select min(a) from table1可以转换为语句2select a from table1 order by a desc limit 1

  语句1生成的逻辑执行计划是一个 TableScan 上面接一个 Aggregation,也就是说这是一个全表扫描的操作。

  语句2生成的逻辑执行计划是TableScan + Sort + Limit,在某些情况,比如a是主键或者是存在索引,数据本身是有序的, Sort 就可以消除,最终变成 TableScan 或者 IndexLookUp 加 Limit,这样子就不需要全表扫了,读到第一条数据就得到结果!全表扫跟只查一条数据,查询速度可是天壤之别。也许这一点点写法上的区别,就是几分钟甚至更长,跟毫秒级响应的差距。

  最大最小消除就是SQL优化器自动把上面的操作实现了。比如说:

  select max(id) from table1 生成的查询计划会变成下面这种(最大消除):

  select max(id) from (select id from table1 order by id desc limit 1 where id is not null) t

  select min(id) from table1生成的查询计划会变成下面这种(最小消除):

  select min(id) from (select id from table1 order by id limit 1 where id is not null) t

  然后转换后的语句再经过其他的转换规则最终得到最后的查询计划。

SQL优化之列裁剪和投影消除的更多相关文章

  1. 简单聊聊TiDB中sql优化的一个规则---左连接消除(Left Out Join Elimination)

    我们看看 TiDB 一段代码的实现 --- 左外连接(Left Out Join)的消除; select 的优化一般是这样的过程: 在逻辑执行计划的优化阶段, 会有很多关系代数的规则, 需要将逻辑执行 ...

  2. 数据库的规范和SQL优化技巧总结

    现总结工作与学习中关于数据库的规范设计与优化技巧 1.规范背景与目的 MySQL数据库与 Oracle. SQL Server 等数据库相比,有其内核上的优势与劣势.我们在使用MySQL数据库的时候需 ...

  3. SQL优化之count(*),count(列)

    一.count各种用法的区别 1.count函数是日常工作中最常用的函数之一,用来统计表中数据的总数,常用的有count(*),count(1),count(列).count(*)和count(1)是 ...

  4. SQL优化器执行过程之逻辑算子

    我们提到了两种SQL优化器,分别是RBO和CBO.那么无论是RBO,还是CBO都包含了一系列优化规则,这些优化规则可以对关系表达式进行等价转换,从而寻找最优的执行计划. 那么常见的优化规则就包括: 列 ...

  5. 深入了解 TiDB SQL 优化器

    分享嘉宾:张建 PingCAP TiDB优化器与执行引擎技术负责人 编辑整理:Druid中国用户组第6次大数据MeetUp 出品平台:DataFunTalk 导读: 本次报告张老师主要从原理上带大家深 ...

  6. sql 优化 链接提示 查询提示 标提示

    SQL Server的查询优化器在select查询执行的时候产生一个高效的查询执行计划.如果优化器不能选择最优的计划,那么就需要检查查询计划.统计信息.支持的索引等,而通过使用提示可以改变优化器选择查 ...

  7. Oracle 建立索引及SQL优化

    数据库索引: 索引有单列索引,复合索引之说,如果某表的某个字段有主键约束和唯一性约束,则Oracle 则会自动在相应的约束列上建议唯一索引.数据库索引主要进行提高访问速度. 建设原则: 1.索引应该经 ...

  8. 大型系统开发sql优化总结(转)

    Problem Description: 1.每个表的结构及主键索引情况 2.每个表的count(*)记录是多少 3.对于创建索引的列,索引的类型是什么?count(distinct indexcol ...

  9. 转://从一条巨慢SQL看基于Oracle的SQL优化

    http://mp.weixin.qq.com/s/DkIPwbDKIjH2FMN13GkT4w 本次分享的内容是基于Oracle的SQL优化,以一条巨慢的SQL为例,从快速解读SQL执行计划.如何从 ...

随机推荐

  1. 观《phonegap第三季 angularjs+ionic视频教程 实时发布》学习笔记(三)

    十五.ionic路由 1.ionic中内联模板介绍 使用内联模板内联模板的使用,常见的有几种情况.(1) 使用ng-include指令可以利用ng-include指令在HTML中直接使用内联模板,例如 ...

  2. python生成百分数

    >>> a = float(5.69875) >>> b = float(8.49385) >>> print a/b 0.67092661160 ...

  3. netstat命令——网络,进程,内存

    netstat网络.进程.内存 转自:https://www.cnblogs.com/xieshengsen/p/6618993.html https://zhidao.baidu.com/quest ...

  4. vc判断当前用户是否具有administrator 权限代码

    BOOL IsAdmin() { HANDLE hAccessToken; BYTE * InfoBuffer = ]; PTOKEN_GROUPS ptgGroups; DWORD dwInfoBu ...

  5. Python简单实现邮件群发

    Python简单实现邮件群发 import smtplib from email.mime.text import MIMEText from email.utils import formatadd ...

  6. Python面向对象中的“私有化”

    Python面向对象中的“私有化” Python并不直接支持私有方式,而要靠程序员自己把握在外部进行特性修改的时机. 为了让方法或者特性变为私有(从外部无法访问),只要在它的名字前面加上双下划线即可. ...

  7. 访问HDFS报错:org.apache.hadoop.security.AccessControlException: Permission denied

    import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apac ...

  8. Android图片加载框架Picasso最全使用教程5

    在之前的四篇博客中,我们学习了所有的关于Picasso的主要方法,我们也对这个Picasso有了一个很深的认识,下面就主要对Picasso自身进行分析,这样的话,会让我们更了解Picasso的核心方法 ...

  9. linux内核打印级别

    1.printk()是一个内核的一个记录日志的机制,经常用来记录信息或者警告.printk可以指定输出日志的优先级,在include/linux/kern_levels.h中有相应的宏定义 #defi ...

  10. [Spring ] RequestParam VS PathVariable

    仔细一想,感觉没啥需要区分的呢.就是简单明确了两种url定义的背景. PathVariable这种,主要是针对restful类型的url.这种path的定义就要根据restful的规范了. 根据昨天开 ...