【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 ...
随机推荐
- win2003能支持的最高python版本为3.3.5版本
https://www.python.org/downloads/windows/
- 基于LVS的负载均衡实现
一 什么是负载均衡 负载均衡,英文名称为Load Balance,其意思就是分摊到多个操作单元上进行执行,例如Web服务器.FTP服务器.企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务 ...
- Python多线程-信号量
信号量就是一个线程中有多个线程 # -*- coding:utf-8 -*- __author__ = "MuT6 Sch01aR" import threading import ...
- 微信小程序API登录凭证(code),获得的用户登录态拥有一定的时效性
调用接口获取登录凭证(code)进而换取用户登录态信息,包括用户的唯一标识(openid) 及本次登录的 会话密钥(session_key).用户数据的加解密通讯需要依赖会话密钥完成. OBJECT参 ...
- Setting up logs in NetBackup
For a given issue, it may be necessary to gather multiple logs. This MUST cover the time the issue ...
- MapReduce和YARN框架
MapReduce组件如图
- php学习第一天-勤劳致富
所谓“勤劳致富”,是很有科学依据的,且是经过我的亲身实践的. 自毕设突然转变为开发项目之后,整个天都变了.先是妹子给我订的票被强行取消,然后又是师兄的一句“***一小时就搞定了”,说明一下这个***是 ...
- 【HDU4960】Another OCD Patient
题意 给出一个长度为n的整数序列.可以将一段连续的序列进行合并.合并的长度不同代价不同.问付出最少多少代价可以将这个序列变成一个对称的序列.n<=5000 分析 一看题感觉是个dp很好写啊.f[ ...
- 刷题向》关于一道像差分约束的数学题BZOJ1045(NORMAL)
关于这道题,乍一看很像查分约束,但是实际上这道题是可以用数学方法直接解决的. 这道题在蓝书上有原题,可以看到题解,在此再赘述一遍 首先,最终每个小朋友的糖果数量可以计算出来,等于糖果总数除以n,用av ...
- php安装memcache
php扩展memcache的作用是为了支持memcached数据库缓存服务器,下面是安装方法. 1.下载并解压memcache文件 1 2 3 wget -c http://pecl.php.net/ ...