列裁剪

  对于没用到的列,则没有必要读取它们的数据去浪费无谓的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. hdu 1513 Palindrome【LCS滚动数组】

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=1513 http://acm.hust.edu.cn/vjudge/contest/view.action ...

  2. Qunit 和 jsCoverage使用方法(js单元测试)

    Qunit 和 jsCoverage使用方法(js单元测试) 近日在网上浏览过很多有关js单元测试相关的文档,工具,但是,针对Qunit 和 jsCoverage使用方法,缺少详细说明,对于初入前端的 ...

  3. 关于Nginx部署Django项目的资料收集

    参考:https://www.cnblogs.com/chenice/p/6921727.html 参考:https://blog.csdn.net/fengzq15/article/details/ ...

  4. Linux下如何安装Anaconda?

    下载 从https://repo.continuum.io/archive/index.html上下载对应版本的Anaconda. 或者到官网:https://www.anaconda.com/dow ...

  5. 序列化组件之生成hypermedialink

    一  生成hypermedialink(极少数) 组件 class BooksSerializer(serializers.ModelSerializer): name = serializers.C ...

  6. python单线程解决并发

    1.单线程解决并发 方式一 import socket import select # 百度创建连接:非阻塞 client1 = socket.socket() client1.setblocking ...

  7. Linux(6)- redis发布订阅/持久化/主从复制/redis-sentinel/redis-cluster、nginx入门

    一.redis发布订阅 Redis 通过 PUBLISH .SUBSCRIBE 等命令实现了订阅与发布模式. 其实从Pub/Sub的机制来看,它更像是一个广播系统,多个Subscriber可以订阅多个 ...

  8. Leetcode注意

    List<List<Integer>> res = new ArrayList<>();

  9. path的join和resolve的使用区别

    文章目录   1.连接路径:path.join([path1][, path2][, ...]) 2.路径解析:path.resolve([from ...], to) 3.对比 1.连接路径:pat ...

  10. PAT 1126 Eulerian Path[欧拉路][比较]

    1126 Eulerian Path (25 分) In graph theory, an Eulerian path is a path in a graph which visits every ...