概述

当查询语句中存在谓词时,能够减少执行阶段需要处理的数据量。为此,Oceanbase中定义了谓词移动规则,能够利用查询语句中各部分已有的谓词推导出新的谓词,并将其尽可能下推至数据读取阶段,从而减少各阶段需要处理的数据量,提升查询性能。

基本原理

SELECT * FROM (SELECT * FROM t1 WHERE c2 < 1000) v1, (SELECT * FROM t2 WHERE c2 > 0) v2
WHERE v1.c1 = v2.c1 AND v1.c2 > v2.c2 AND v1.c1 > 0;

对于上述查询,可以对其进行谓词推导和下推改写,从而减少需要读取的数据量,如下所示:

SELECT * FROM (SELECT * FROM t1 WHERE c1 > 0 AND c2 > 0 AND c2 < 1000) v1, (SELECT * FROM t2 WHERE c1 > 0 AND c2 > 0 AND c2 < 1000) v2
WHERE v1.c1 = v2.c1 AND v1.c2 > v2.c2; 

代码解析

谓词移动规则的入口为ObTransformPredicateMoveAround::transform_one_stmt,执行流程如下:

  1. 调用pullup_predicates函数对满足条件的视图表或集合子查询中的谓词执行提升收集。

  1. 调用pushdown_predicates函数对父查询中的谓词结合前一步收集的谓词执行下推。

pullup_predicates函数负责递归地将视图表中的谓词收集到集合中,执行流程如下:

  1. 调用acquire_transform_params函数为当前语句分配谓词集合(下称input_pullup_preds),供后续流程使用。

  1. 如果当前语句为集合语句,则执行如下流程进行处理:

  1. 调用pullup_predicates_from_set函数对集合语句子查询中的谓词进行提升收集。

  1. 调用generate_set_pullup_predicates函数提取pullup_preds中能够向上提升的谓词(即涉及的参数列均位于集合语句的select列表中的谓词),用于返回父查询。

  1. 调用acquire_transform_params函数获取为当前语句分配的谓词集合,将收集到的谓词保存到该集合中。

  1. 如果当前语句不为集合语句,则执行如下流程进行处理:

  1. 调用preprocess函数将semi信息及join表中能够提升的条件移动到当前语句的where条件中。

  1. 调用pullup_predicates_from_view函数将当前语句的视图表中的谓词收集到input_pullup_preds中。

  1. 如果当前语句为视图查询语句或集合子查询,则调用generate_pullup_predicates函数结合当前语句的where条件、having条件及input_pullup_preds中的谓词进行推导,将得到的谓词集合返回父查询。

pullup_predicates_from_set函数会遍历集合语句的子查询,对其中的谓词进行收集,执行流程如下:

  1. 调用pullup_predicates函数收集子查询语句中的谓词。

  1. 调用rename_set_op_predicates函数将上述谓词涉及的子查询中的列表达式转换为集合语句的列表达式。

  1. 调用check_pullup_predicates函数将各子查询得到的谓词集合进行合并,根据集合操作的类型,执行逻辑如下:

  1. 如果集合操作为union,则合并时取谓词集合的交集。

  1. 如果集合操作为intersect,则合并时取谓词集合中不在交集中的谓词。

  1. 如果集合操作为except,则合并时直接使用第一条子查询的谓词集合。

pullup_predicates_from_view函数负责提升收集当前查询语句下的视图表中的谓词,执行流程如下:

  1. 调用get_columns_in_filters函数抽取当前语句的where条件、having条件、join表连接条件、半连接条件及参数指定的select列表达式涉及的列(下称filter_columns)。

  1. 遍历当前语句的表信息,对于其中的视图表,如果其没有作为外连接的内表,则执行如下流程对其中的谓词进行提升收集:

  1. 调用choose_pullup_columns函数从filter_columns中筛选属于当前视图表的列(下称view_sel_list)。

  1. 调用pullup_predicates函数对视图查询中view_sel_list中的列的谓词进行提升收集。

  1. 调用rename_pullup_predicates函数将收集的谓词集合中视图查询的select列转换为对应父查询中的列。

generate_pullup_predicates函数负责利用已有谓词进行推导,该函数会使用从视图表收集的谓词、当前语句的where条件和having条件的并集作为输入谓词,调用compute_pullup_predicates函数执行推导,处理流程如下:

  1. 使用父查询指定的select列偏移,收集视图查询中对应的select列作为目标列。

  1. 调用transform_predicates函数,使用上述输入谓词和目标列进行谓词推导。

  1. 遍历推导结果中的谓词,将满足如下条件的结果添加到最终的谓词集合中:

  1. 当前谓词应该为简单谓词(>, >=, <, <=, =)或通用谓词(between, like, <>, in),且不能为常量表达式。

  1. 当前谓词涉及的参数应该都包含于目标列中。

transform_predicates函数负责使用输入谓词和目标列进行谓词推导,对原有谓词集合进行扩展,执行流程如下:

  1. 将输入谓词划分为可以参与推导图构建的谓词集合(即valid_preds)和其他谓词集合(即other_preds)。

  1. 使用valid_preds构建推导图,然后按照如下流程进行谓词推导:

  1. 调用ObPredicateDeduce::deduce_simple_predicates函数,基于谓词参数的比较关系传导性,推导出普通谓词(下称simple_preds)。

  1. 调用ObPredicateDeduce::deduce_general_predicates函数,基于谓词参数的比较关系传导性,推导出通用谓词((下称general_preds)。

  1. 调用ObPredicateDeduce::deduce_aggr_bound_predicates函数,基于谓词参数的比较关系传导性,推导出聚合范围谓词(下称aggr_bound_preds)。

  1. 将simple_preds、other_preds、general_preds和aggr_bound_preds中的谓词合并到集合中。

pushdown_predicates负责将提升收集得到谓词进行下推,执行流程如下:

  1. 调用acquire_transform_params函数获取提升收集阶段得到的谓词集合(下称pullup_preds)。

  1. 如果当前语句为集合语句,则调用pushdown_into_set_stmt函数将谓词下推到集合语句的子查询中。

  1. 如果当前语句不为集合语句,则执行如下流程进行处理:

  1. 调用pushdown_through_winfunc函数获取参数谓词集合中能够通过窗口函数继续下推的谓词(下称candi_preds)。

  1. 调用pushdown_into_having函数将candi_preds中的谓词推导下推至having条件中。

  1. 调用pushdown_through_groupby函数基于having条件构建下推谓词集合作为新的candi_preds。

  1. 调用pushdown_into_where函数将candi_preds中的谓词推导下推至where条件中。

  1. 遍历查询语句中的semi信息,调用pushdown_into_semi_info函数将where条件中的谓词推导下推至半连接条件及右表中。

  1. 遍历查询语句中的from表,调用pushdown_into_table函数将where条件中谓词推导下推至from表中。

pushdown_into_set_stmt函数会遍历集合语句的子查询,将谓词下推到子查询语句中,执行流程如下:

  1. 对子查询调用重载的pushdown_into_set_stmt函数进行下推,后者执行流程如下:

  1. 调用rename_set_op_predicates函数将下推谓词涉及的集合语句的列表达式转换为子查询中的列表达式。

  1. 调用pushdown_predicates函数将谓词下推到子查询语句中。

  1. 将参数谓词集合更新为没有成功下推的谓词。

  1. 调用check_pushdown_predicates函数将各子查询没有下推的谓词集合进行合并,根据集合操作的类型,执行逻辑如下:

  1. 如果集合操作为union,则合并时取谓词集合的并集。

  1. 如果集合操作为intersect,则合并时取谓词集合的交集。

  1. 如果集合操作为except,则合并时直接使用第一条子查询的谓词集合。

pushdown_through_winfunc函数首先会遍历当前语句中的窗口函数,找到共同的分区列(下称common_part_exprs)。然后遍历所有的下推谓词,将不包含窗口函数且涉及的列为common_part_exprs子集的表达式加入新的下推集合中。

pushdown_into_having函数首先会抽取pullup_preds中from表的谓词(下称input_preds)以及查询语句的列集合中属于from表的列(下称columns),使用input_preds、candi_preds和查询语句的having条件的并集作为输入谓词,columns作为目标列进行谓词推导,然后将过滤掉pullup_preds中的谓词后的推导结果设置为新的having条件。

pushdown_through_groupby函数会遍历having条件中的条件表达式,然后将满足下推条件的谓词经过转换后加入下推集合并从having条件中移除,处理逻辑如下:

  1. 如果当前条件为关系比较表达式,而其中的左右参数分别为min/max聚合函数和常量表达式,且当前语句只包含一个聚合项时,则可以用聚合函数的参数列替代聚合函数构成新的谓词加入谓词集合中。

  1. 如果当前条件涉及的列为group by表达式的子集,则将该条件加入谓词集合。

pushdown_into_where函数首先会抽取pullup_preds中from表的谓词(下称input_preds)以及查询语句的列集合中属于from表的列(下称columns),使用input_preds、candi_preds和查询语句的where条件的并集作为输入谓词,columns作为目标列进行谓词推导,然后将过滤掉pullup_preds中的谓词后的推导结果设置为新的where条件。

pushdown_into_semi_info函数首先会抽取pullup_preds中属于当前semi join左(右)表的谓词、where条件中的属于当前seim join左表的谓词,以及查询语句的列集合中属于当前seim join右表的列(下称cols),将上述谓词集合的并集(下称properites)与当前semi信息中的连接条件一同作为输入谓词,cols作为目标列进行谓词推导,然后将过滤掉properites中的谓词后的推导结果设置为新的连接条件。对于连接条件中的右表谓词,该函数会继续调用pushdown_into_table函数,尝试将其推入右表中。如果此时连接条件中还有没有被成功下推的右表谓词,则调用ObTransformUtils::pushdown_semi_info_right_filter函数将其推入右表视图的where条件中(如果右表不是视图表,则为其创建视图)。

pushdown_into_table函数负责将谓词下推至表的内部,执行流程如下:

  1. 调用get_pushdown_predicates函数,获取属于当前表的下推谓词集合。

  1. 根据表的类型,执行如下下推逻辑:

  1. 如果表为基表,则不进行下推。

  1. 如果表为视图表,则按照如下流程进行下推:

  1. 调用rename_pushdown_predicates函数将谓词中视图表导出的列替换为视图查询的select列。

  1. 调用choose_pushdown_preds函数选择下推谓词中符合下推条件的谓词,即不包含子查询的谓词。

  1. 调用pushdown_predicates函数将符合条件的谓词下推至视图查询中。

  1. 如果表为join表,则调用pushdown_into_joined_table函数进行下推。

  1. 从谓词参数集合中移除成功下推的谓词。

pushdown_into_joined_table函数负责将谓词下推至join表,执行流程如下:

  1. 如果当前连接不为full连接,则将谓词下推至当前连接条件,执行流程如下:

  1. 抽取查询语句的列集合中属于当前连接内表侧的列(即左连接的右表、右连接的左表及内连接的左右两表中的列,下称cols),将pullup_preds和下推谓词的并集(下称properites)与当前连接条件一同作为输入谓词(下称all_preds),cols作为目标列进行谓词推导,得到新的谓词集合(下称new_preds)。

  1. 根据连接类型,执行如下下推逻辑:

  1. 如果为内连接,则使用new_preds中不在properites中谓词作为新的连接条件。

  1. 如果为外连接,则使用原连接条件中的谓词与new_preds中属于内表侧条件且不在all_preds中谓词的并集作为新的连接条件。

  1. 如果当前连接不为full连接,则将谓词下推至子节点,执行流程如下:

  1. 为左右节点选择下推谓词。如果当前连接为左连接,则将参数谓词集合作为左下推参数(下称left_down),连接条件作为右下推参数(下称right_down),右连接则相反;如果为当前连接为内连接,则将参数谓词集合和连接条件的并集作为左右下推参数。

  1. 使用上一步得到的下推参数,对左右节点分别调用pushdown_into_table函数。

  1. 将参数谓词集合和连接条件更新为没有被成功下推的谓词。如果当前连接为左连接,则将参数谓词集合设置为left_down,连接条件设置为right_down,右连接则相反;如果为当前连接为内连接,则将参数谓词集合中同时存在于left_down和right_down中的谓词集合作为新的参数谓词集合,连接条件中同时存在于left_down和right_down中的谓词集合作为新的连接条件。

Oceanbase查询改写:谓词移动相关推荐

  1. Oceanbase查询改写:查询下推

    概述 默认情况下,当查询语句中存在视图时,需要等待视图中的查询执行完毕后再执行父查询.为此,Oceanbase中定义了查询下推规则,能够将满足条件的父查询下推合并到视图查询中,从而消除视图,提升查询性 ...

  2. 《深入理解Elasticsearch(原书第2版)》一2.2 查询改写

    本节书摘来自华章出版社<深入理解Elasticsearch(原书第2版)>一书中的第2章,第2.2节,作者[美]拉斐尔·酷奇(Rafal Ku) 马雷克·罗戈任斯基(Marek Rogoz ...

  3. 美团搜索中查询改写技术的探索与实践

    猜你喜欢 0.[免费下载]2022年1月热门报告盘点1.腾讯QQ信息流推荐业务实践2.小红书推荐中台实践3.微信视频号的实时推荐技术架构分享4.预训练模型在华为信息流推荐系统中的探索和应用5.腾讯PC ...

  4. 16、子查询改写为表连接

    子查询如递归函数一样,有时侯能达到事半功倍的效果,但是其执行效率较低.与表连接相比,子查询比较灵活,方便,形式多样,适合作为查询的筛选条件,而表连接更适合查看多表的数据. 一般情况下,子查询会产生笛卡 ...

  5. 查询改写(Query Rewrite)方法总结

    为何需要Query改写 Query分析是搜索引擎的一个重要模块,对搜索结果的覆盖率和相关性至关重要.搜索引擎的检索过程包含了两个重要的阶段:匹配和排序.匹配也叫召回,表示根据用户的查询条件,尽可能多地 ...

  6. oracle如何查询排行第二,Oracle优化查询改写(第二章-给查询结果排序)

    2.1以指定的次序返回查询结果 select empno,ename,hiredate from emp where deptno =10 order by hiredate 或者 select em ...

  7. 【直播预约】数据库OBCP认证全面升级公开课

    深入浅出 OceanBase 社区线上技术沙龙,旨在帮助关注分布式数据库技术的爱好者们提供技术交流.分享和探讨的线上空间. 每月围绕 OceanBase 核心技术和周边工具展开,大胆说出你想听的话题, ...

  8. 【SQL】(task3)复杂查询(视图 | 子查询 | 谓词 | Case)

    学习总结 (1)视图和子查询.对于一些复杂的查询需要使用子查询加一些条件语句组合才能得到正确的结果.一个SQL语句的层数不能过深,不然可读性差而且执行效率也难以保证,所以尽量有简洁的语句来完成需要的功 ...

  9. 最清晰!一篇文章读懂 OceanBase 最新的产品家族

    OceanBase 具有强大的内核功能,联机交易+决策分析,可解决大部分 TP和 AP 场景需求.计算引擎融合 KV.文档.时序.图和空间,实现多模支持,当前时序数据库已发布,同时配套 OMS 数据迁 ...

最新文章

  1. 一个5位数,判断它是不是回文数。即12321是回文数,个位与万位相同,十位与千位相同。...
  2. [Linux].netrc或者_netrc使用可以
  3. 招聘 | 南京柯基数据招聘自然语言处理工程师
  4. vue打卡日历_Vue日历
  5. 如果奇迹有颜色,那么一定是暴力or模拟比较6
  6. 第三节:python 交互和调用参数
  7. 2014年物联网Internet of Things应用简介
  8. RN开发环境搭建-window
  9. VMware Horizon环境中的防病毒注意事项
  10. 2016——注定不平凡的一年
  11. windows10安装虚拟机详细教程
  12. 区块链游戏常见的 10 种分类
  13. java 累加器_09-flink-Accumulator(累加器)
  14. C语言%lld、%llu无法正常输出比long long长整数小的数
  15. 根据文件路径区分文件的所属类型,并返回对应类型的文件路径
  16. C++ websocket 使用体验
  17. dll修复工具哪个比较好?好的修复工具怎么选择
  18. TNS-12543: TNS:destination host unreachable
  19. 透视C# Span<T>数据结构
  20. 谁知nmn的功效与作用,nmn真实效果图,吐血整理

热门文章

  1. 从Q萌到硬核:全面升级背后的默默扎根
  2. 珍藏多年绿帽子斗图必胜表情包
  3. nginx那点事儿——nginx日志详解
  4. 浏览器调试之js调试
  5. 看了变形金刚的首映 ^_^
  6. 经典卷积网络--VGGNet
  7. java中的Set集合详解
  8. 百家号如何过新手期,百家号怎么做爆文开始赚钱
  9. 年过40的前华为工程师,来面P7技术专家,你猜最后通过了吗?
  10. 什么是闭包,Python闭包(初学者必读)