【kudu pk parquet】runtime filter实践
已经有好一阵子没有写博文了,今天给大家带来一篇最近一段时间开发相关的文章:在impala和kudu上支持runtime filter。
- 表结构:
create table orders
(
o_orderkey bigint, -> 主键,也是分区键(分布式数据库用于数据分片)
o_custkey bigint, -> 外键,同customer.c_custkey
o_orderstatus string,
o_totalprice double,
o_orderdate string,
o_orderpriority string,
o_clerk string,
o_shippriority bigint,
o_comment string
)
create table customer
(
c_custkey bigint, -> 主键,也是分区键
c_name string,
c_address string,
c_nationkey bigint,
c_phone string,
c_acctbal double,
c_mktsegment string,
c_comment string
)
- 测试sql:
select c.* from orders o join customer c on c.c_custkey = o.o_custkey where o_orderkey = 1125;
我们用业界的TPC-H工具生成1TB的测试数据,使用上面的sql语句来测试orders和customer两表关联。
- 在impala-shell执行sql:

- 查看profile:
F02:PLAN FRAGMENT [UNPARTITIONED] hosts=1 instances=1
PLAN-ROOT SINK
| mem-estimate=0B mem-reservation=0B
|
04:EXCHANGE [UNPARTITIONED]
| mem-estimate=0B mem-reservation=0B
| tuple-ids=1,0 row-size=251B cardinality=2
|
F00:PLAN FRAGMENT [RANDOM] hosts=3 instances=3
02:HASH JOIN [INNER JOIN, BROADCAST] -> 以hashJoin的方式两表关联
| hash predicates: c.c_custkey = o.o_custkey -> 用“c.c_custkey = o.o_custkey”条件关联
| mem-estimate=9B mem-reservation=136.00MB
| tuple-ids=1,0 row-size=251B cardinality=2
|
|--03:EXCHANGE [BROADCAST]
| | mem-estimate=0B mem-reservation=0B
| | tuple-ids=0 row-size=8B cardinality=1
| |
| F01:PLAN FRAGMENT [RANDOM] hosts=3 instances=3
| 00:SCAN KUDU [kudu_1000g.orders o] -> 扫描orders表
| kudu predicates: o_orderkey = 1125 -> 用“o_orderkey = 1125”条件过滤
| mem-estimate=0B mem-reservation=0B
| tuple-ids=0 row-size=8B cardinality=1
|
01:SCAN KUDU [kudu_1000g.customer c] -> 扫描customer表
mem-estimate=0B mem-reservation=0B -> 没有过滤条件,返回全部数据
tuple-ids=1 row-size=243B cardinality=150000000
profile中已经做了一些批注,概括一下就是:
- 查看plan:

- 谓词,就是filter或者过滤器,条件表达式;
- 静态则表示的是来自于sql语句本身,动态即运行过程中产生,也即runtime;
- 动态谓词就是runtime filter。
- 在impala-shell执行sql:

- 查看profile:
F02:PLAN FRAGMENT [UNPARTITIONED] hosts=1 instances=1
PLAN-ROOT SINK
| mem-estimate=0B mem-reservation=0B
|
04:EXCHANGE [UNPARTITIONED]
| mem-estimate=0B mem-reservation=0B
| tuple-ids=1,0 row-size=251B cardinality=2
|
F00:PLAN FRAGMENT [RANDOM] hosts=3 instances=3
02:HASH JOIN [INNER JOIN, BROADCAST] -> 以hashJoin的方式两表关联
| hash predicates: c.c_custkey = o.o_custkey -> 用“c.c_custkey = o.o_custkey”条件关联
| runtime filters: RF000 <- o.o_custkey -> 这里生成了1个runtime filter
| mem-estimate=9B mem-reservation=136.00MB
| tuple-ids=1,0 row-size=251B cardinality=2
|
|--03:EXCHANGE [BROADCAST]
| | mem-estimate=0B mem-reservation=0B
| | tuple-ids=0 row-size=8B cardinality=1
| |
| F01:PLAN FRAGMENT [RANDOM] hosts=3 instances=3
| 00:SCAN KUDU [kudu_1000g.orders o] -> 扫描orders表
| kudu predicates: o_orderkey = 1125 -> 用“o_orderkey = 1125”条件过滤
| mem-estimate=0B mem-reservation=0B
| tuple-ids=0 row-size=8B cardinality=1
|
01:SCAN KUDU [kudu_1000g.customer c] -> 扫描customer表
runtime filters: RF000 -> c.c_custkey -> 这里应用了1个runtime filter
mem-estimate=0B mem-reservation=0B
tuple-ids=1 row-size=243B cardinality=150000000
- 查看plan:

- 对于runtime filter,我们需要明白谁产生和谁使用的关系,前者仅由关联节点生成,而后者仅由扫描节点使用,两者都属于计算引擎。其中扫描节点在使用runtime filter上有两种方式,一种是把runtime filter直接推送到存储引擎,离数据最近,理论上效果肯定是最佳的,我们选择的正是这种方式;还有一种是在扫描节点上过滤,把远端数据全部读取过来进行本地过滤,可以减少流入上层关联节点的数据量,比如parquet就是这种方式。这里有必要说明下parquet的特殊之处,它可以选择采用hdfs的short circuit,简短的理解:作为分布式文件系统的hdfs,它的数据文件是以block文件块的形式组织起来的,而parquet的数据是放在一个个的block上,在impala和hdfs配对部署的前提下,当impala把需要扫描block文件块的计算任务分配到block文件块所在的impala节点上,那这个impala计算节点就可以直接通过操作系统的文件系统读block文件块,省去了hdfs分布式文件系统的中间层传输开销;
- runtime filter的类型可以有很多种:包括min/max(范围区间,或者大于、小于)、in list(数组)、bloom filter(布隆过滤器)、equality(等值)等,但是在目前的impala里仅支持bloom filter,这是万金油,最方便实现,后续我们可以考虑引入其他的类型,降低存储引擎扫描时候的计算量(节约CPU计算时间)。从kudu官方来看,一直建议使用min/max或者in list的方式进行下推,估计同修改的工作量有关,因为它目前的通信协议是不支持bloom filter这种谓词下发,而且两边(impala和 kudu)的bloom filter算法也是不一样的;
- 分布式计算引擎,对扫描返回的数据做重分布(repartition或者shuffle)后,会生成一个统一的runtime filter,这个工作由coordinator集中merge再分发给各个计算节点,并且在左子树上,只要关联字段一样,它会一直推送到最底层的扫描节点;同一个列,多份runtime filter、多种谓词,通过merge的方式进行合并,比如bloom filter + range组合,range + range组合等等;
- 通常数据扫描节点在启动扫描以后,就不会再更新过滤器,也即不会再下发新的谓词,因为本身这个过程就已经比较复杂。但是我们的修改,可以支持在扫描过程的中间(mid-scan),把新的runtime filter下发下去,并且在kudu存储引擎层进行直接应用,这对于缩小返回的数据集非常有帮助;
- 最后一个是关于runtime filter应用于裁剪数据分片,这个意义也比较大,决定着响应时间。可以分两步:第一步是针对分区键,比较容易理解,就是启动扫描或者扫描的中间,把不需要扫描的数据分片直接跳过,有同学可能会说,关联键不一定是分区键哦,是的,这时,我们就需要第二步,针对非分区键的索引(俗称二级索引),实现上可以有多种方案,比如针对分片的min/max或者bitmap等,但是工作量都不小呢:(;
本文来自网易云社区,经作者何李夫授权发布。
原文地址:【kudu pk parquet】runtime filter实践
更多网易研发、产品、运营经验分享请访问网易云社区。
【kudu pk parquet】runtime filter实践的更多相关文章
- 【kudu pk parquet】TPC-H Query2对比解析
这是[kudu pk parquet]的第二篇,query2在kudu和parquet上的对比解析,其中kudu包含有不能下发的谓词. 3台物理机,1T规模的数据集,impala和kudu版本是我们修 ...
- 【原创】大叔经验分享(63)kudu vs parquet
一 对比 存储空间对比: 查询性能对比: 二 设计方案 将数据拆分为:历史数据(hdfs+parquet+snappy)+ 近期数据(kudu),可以兼具各种优点: 1)整体低于10%的磁盘占用: 2 ...
- runtime MethodSwizzle 实践之扩展 NIAttributedLabel
runtime MethodeSwizzle 提供 简单的方法交换已知类的 Method IMP. Method 可以是 外部可访问的 public 或者 private Method .所谓的属性 ...
- runtime MethodSwizzle 实践之 奇怪crash : [UIKeyboardLayoutStar release]: message sent to deallocated instance
情景: 使用MethodSwizzle 实现对数组.字典 等系统方法的安全校验.显然能达到预期效果,但实际发现当 键盘显示的情况下 home app 进入后台,再单击app 图标 切换回前台时 发 ...
- iOS Runtime 实践(1)
很多时候我们都在看iOS开发中的黑魔法——Runtime.懂很多,但如何实践却少有人提及.本文便是iOS Runtime的实践第一篇. WebView 我们这次的实践主题,是使用针对接口编程的方式,借 ...
- 【大数据之数据仓库】kudu性能测试报告分析
本文由 网易云发布. 这篇博文主要的内容不是分析说明kudu的性能指标情况,而是分析为什么kudu的scan性能会这么龊!当初对外宣传可是加了各种 逆天黑科技的呀:列独立存储.bloom filte ...
- 基于 Apache Hudi 极致查询优化的探索实践
摘要:本文主要介绍 Presto 如何更好的利用 Hudi 的数据布局.索引信息来加速点查性能. 本文分享自华为云社区<华为云基于 Apache Hudi 极致查询优化的探索实践!>,作者 ...
- Presto 在字节跳动的内部实践与优化
在字节跳动内部,Presto 主要支撑了 Ad-hoc 查询.BI 可视化分析.近实时查询分析等场景,日查询量接近 100 万条.本文是字节跳动数据平台 Presto 团队-软件工程师常鹏飞在 Pre ...
- 华为云 MRS 基于 Apache Hudi 极致查询优化的探索实践
背景 湖仓一体(LakeHouse)是一种新的开放式架构,它结合了数据湖和数据仓库的最佳元素,是当下大数据领域的重要发展方向. 华为云早在2020年就开始着手相关技术的预研,并落地在华为云 Fusio ...
随机推荐
- Java-Maven-Runoob:Maven 依赖管理
ylbtech-Java-Maven-Runoob:Maven 依赖管理 1.返回顶部 1. Maven 依赖管理 Maven 一个核心的特性就是依赖管理.当我们处理多模块的项目(包含成百上千个模块或 ...
- Linux学习笔记 -- 系统目录结构
以root用户登录系统后,在当前命令窗口下输入命令: ls / 我们可以看到目录结构类似下图: 树状目录结构可以表示为: 解析: /bin:bin是Binary的缩写, 这个目录存放着最经常使用的命令 ...
- vs2017 android demo
vs2017自安装以后就没怎么打开过,虽然12出的时候用10,15出的时候用13,17出的时候用15,但我依然坚持不用也装上再说的理念. 1.vs2017开发IOS和Android安装所必不可少的,u ...
- 解决word自动编号出现内容空格过大的问题
选择你需要调整的段落.右键点击.选择“调整列表缩进” 然后在弹出的窗口中,第三行的“制表符”改成“空格”即可.或者空格都不需要可以改为“不特别标注”. 当编号超过10的时候,也会有空格太大的现象,这时 ...
- php写一个判断是否有cookie的脚本
前言: 刚刚学习完cookie函数,写个练习. 0x01: //其实第二个应该改为elseif,但是我懒.啊哈 <?php $vlas="BnJhiFoPS4"; if(is ...
- javascript中的垃圾回收
1引用计数垃圾回收 核心:跟踪记录对象被引用的次数.思路是如果一个对象A被赋值给了一个变量v,则该对象A的引用计数值加1,如果变量v又被赋予其他值了,比如a="str",则该对象A ...
- jenkins 学习记录1
主题 以前自己做些小玩意儿比如博客(http://blogv3.labofjet.com/)的时候,在远程服务器上的tomcat发布工程用的是目录的结构,而不是war.原因很简单.用目录结构的话每次只 ...
- android 命名规则
包名结构: 资源命名方式:
- [android] setOnTouchEvent 设置返回值为true 和 false的区别
今天在做自定义的可选文本的 TextView 类时,用到了 View 类的 setOnTouchListener(OnTouchListener l)事件监听,在构造 OnTouchListener ...
- JAVA基础知识总结15(集合容器)
集合框架:用于存储数据的容器. 1:对象封装数据,对象多了也需要存储.集合用于存储对象. 2:对象的个数确定可以使用数组,但是不确定怎么办?可以用集合.因为集合是可变长度的. 集合和数组的区别: 1: ...