这一章主要涉及TiDB如下的源码:

  1. 扫表算子怎样转换为扫索引算子;

  2. 怎样把Selection算子的过滤条件化简, 转为区间扫描;

假设我们有一个表:

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

其中, id 是主键, a 是索引;

我们执行如下的 sql:

select a from t1 where a= or ( a> and (a> and a <)  and a<);

这条 sql 的最终执行计划是这样的:

+---------------+--------+-----------+-----------------------------------------------------------------------+
| id | count | task | operator info |
+---------------+--------+-----------+-----------------------------------------------------------------------+
| IndexReader_6 | 260.00 | root | index:IndexScan_5 |
| └─IndexScan_5 | 260.00 | cop[tikv] | table:t1, index:a, range:[5,5], (6,8), keep order:false, stats:pseudo |
+---------------+--------+-----------+-----------------------------------------------------------------------+  

这是一个索引扫描的执行计划, 索引扫描区间是 [5,5], (6,8);

我们转到源代码, 看这样的计划是怎样生成的;

这是解析 sql 之后最初生成的执行计划:

在调用 logicalOptimize 函数做逻辑优化之后, 执行计划变为下面这样:

Selection算子哪儿去了?

Selection算子被下推到了 DataSource 算子中, 在 DataSource 的 pushedDownConds 中保存着下推的过滤算子, 是这样的:

这样的一个递归的树状的过滤算子很难在索引扫描中使用, 因为索引底层是顺序排列的, 所以要将这颗树转为扫描区间;

在物理优化中, 会调用 DetachCondAndBuildRangeForIndex 来生成扫描区间, 这个函数会递归的调用如下 2 个函数:

detachDNFCondAndBuildRangeForIndex, 展开 析取范式(DNF), 生成扫描区间或合并扫描区间;
detachCNFCondAndBuildRangeForIndex, 展开 合取范式(CNF), 生成扫描区间或合并扫描区间;

上面的表达式树最终生成了这样的区间: [5,5], (6,8) --- "[" 是开区间, "(" 是闭区间,  递归被消除了;

接下来, 这个索引扫描会加入到 DataSource 的备选的访问表的方法中;

在 DataSource 的 possibleAccessPaths 里保存了访问表的可能的方案, 这里是 2 个方案:

  1. 全表扫描, 用表达式树进行过滤: a=5 or ( a>5 and (a>6 and a <8) and a<12);

  2. 扫索引 a 列, 执行区间扫描 [5,5], (6,8);

物理优化阶段, 会从算子树的根节点递归调用每个算子的 findBestTask 函数, DataSoure 算子会从 possibleAccessPaths  获取最优的执行计划;

这里用到了 skyline pruning 算法, 从多个维度来判断哪个执行计划更优, 最后用索引扫描算子替换掉 DataSource 算子;

最终生成了这样的执行计划:

结束;

												

肤浅的聊聊 TiDB 扫表算子, 扫索引算子, 合取范式(CNF), 析取范式(DNF), skyline pruning的更多相关文章

  1. 肤浅的聊聊关联子查询,数据集连接,TiDB代码,关系代数,等等

    本章涉及的内容是TiDB的计算层代码,就是我们编译完 TiDB 后在bin目录下生成的 tidb-server 的可执行文件,它是用 go 实现的,里面对 TiPD 和 TiKV实现了Mock,可以单 ...

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

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

  3. 隔行扫瞄/逐行扫瞄的介绍(Interlaced / Progressive)

    隔行扫瞄/逐行扫瞄的介绍(Interlaced / Progressive)   本篇不是着重在理论说明, 而是实际验証结果的分享, 所以只简略解释何谓交错与非交错, 请参考如后. 交错扫瞄(隔行扫瞄 ...

  4. 关于数据库表中的索引及索引列的CRUD

     -- 查询一个数据库表中的索引及索引列use [RuPengWangDB]GOSELECT  indexname = a.name , tablename = c. name , indexcolu ...

  5. 无法重新组织表 "ty_wf_ex_local_process_info" 的索引 "idx_prc_act_id" (分区 1),因为已禁用页级锁定。

    无法重新组织表 "ty_wf_ex_local_process_info" 的索引 "idx_prc_act_id" (分区 1),因为已禁用页级锁定. ALT ...

  6. Mysql数据库表排序规则不一致导致联表查询,索引不起作用问题

    Mysql数据库表排序规则不一致导致联表查询,索引不起作用问题 表更描述: 将mysql数据库中的worktask表添加ishaspic字段. 具体操作:(1)数据库worktask表新添是否有图片字 ...

  7. SQL优化的四个方面,缓存,表结构,索引,SQL语句

    一,缓存 数据库属于 IO 密集型的应用程序,其主要职责就是数据的管理及存储工作.而我们知道,从内存中读取一个数据库的时间是微秒级别,而从一块普通硬盘上读取一个IO是在毫秒级别,二者相差3个数量级.所 ...

  8. 单表扫描,MySQL索引选择不正确 并 详细解析OPTIMIZER_TRACE格式

    单表扫描,MySQL索引选择不正确 并 详细解析OPTIMIZER_TRACE格式     一 表结构如下:  万行 CREATE TABLE t_audit_operate_log (  Fid b ...

  9. SQL Server 查看指定表上的索引

    解决方案: sys.indexs; ---------------------------------------------------------------------------------- ...

随机推荐

  1. Django框架深入了解_04(DRF之url控制、解析器、响应器、版本控制、分页)

    一.url控制 基本路由写法:最常用 from django.conf.urls import url from django.contrib import admin from app01 impo ...

  2. Luogu4069 SDOI2016 游戏 树链剖分、李超线段树

    传送门 每一次加的是一个一次函数,一些呈一次函数的线段求最小值,显然用到李超线段树. 然后把维护序列的李超线段树强行上树,就直接套上树剖就可以了. 至于李超树如何区间查询,因为一次函数线段的最小值一定 ...

  3. delphi indy Idhttp error:1409442E:SSL routines:SSL3_READ_BYTES:tlsv1 alert protocol version

    在使用 indy 中的 idhttp 组件访问 https 网站时,出现如下错误: error:1409442E:SSL routines:SSL3_READ_BYTES:tlsv1 alert pr ...

  4. bean标签解析与注册

    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { BeanDefin ...

  5. JSP 9大隐式对象和四个作用域的范围

    Java中 九大隐式对象说明 输入/输出对象:  request   response   out 作用域通信对象: session  application  pageContext Servlet ...

  6. NetworkStream的使用(TcpClient,TcpListener)

    1.在tcp连接中,Networkstream可以重复读取,重复写入,不用关掉连接. 2.关掉NetworkStream会自动关闭掉Tcp连接 3.NetworkStream不需要使用Flush方法, ...

  7. DBCP数据库连接池初探

    1. 概述 数据库连接是很“宝贵的”,如果每次获取Connection都去创建数据库连接,使用之后就断开,再次使用又重新创建,程序效率是很低的.因为Socket连接的建立很消耗资源. 所以需要数据库连 ...

  8. Awesome Mac OS Command Line 中文翻译

    awesome-macos-command-line 收集了很多有趣的 Mac 终端命令. 看了一遍后,发现帮助很大. 见识许多没有使用过的命令,加深了对 Mac 的认识. 所以翻译成了中文,共享给其 ...

  9. IObit Driver Booster 无法更新驱动的解决办法

    IObit Driver Booster 无法更新驱动的解决办法:依次打开软件中的 菜单-设置-网络-自定义代理设置-主机:填入210.101.131.231 端口:8080 最后点确定完成. 注意! ...

  10. Computer Vision_33_SIFT: A novel point-matching algorithm based on fast sample consensus for image registration——2015

    此部分是计算机视觉部分,主要侧重在底层特征提取,视频分析,跟踪,目标检测和识别方面等方面.对于自己不太熟悉的领域比如摄像机标定和立体视觉,仅仅列出上google上引用次数比较多的文献.有一些刚刚出版的 ...