【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 ...
随机推荐
- PHP实现日志写入log.txt
引言:有时候调试,看不到效果,需要通过写入文件来实现. 案例: <?php $myfile = fopen("log.txt", "a+") or die ...
- 第2章 深入分析java I/O的工作机制(下)
2.6 设计模式解析之适配器模式 2.6.1 适配器模式的结构 把一个类的接口变换成一客户端能接受的另一个接口. Target(目标接口): 要转换的期待的接口. Adaptee(源角色):需要适配的 ...
- requests的响应返回值显示content和text方法的区别
requests的get或者post请求,返回的响应response获取方法:content和text content用于获取图片,返回二进制数据 text用于获取内容,返回的是unicode解码字符 ...
- <正则吃饺子> :关于redis集群的搭建、集群测试、搭建中遇到的问题总结
项目中使用了redis ,对于其基本的使用,相对简单些,根据项目中已经提供的工具就可以实现基本的功能,但是只是这样的话,对于redis还是太肤浅,甚至刚开始时候,集群.多节点.主从是什么,他们之间是什 ...
- Cause: java.sql.SQLException: 无效的列索引
今天调试代码发现“Cause: java.sql.SQLException: 无效的列索引”,查资料得出结论如下: 1.sql串的?号用''括了起来. 例如:select* from user t ...
- apk安装包信息
String archiveFilePath="sdcard/DangDang.apk";//安装包路径 PackageManager pm = getPacka ...
- Spark,一种快速数据分析替代方案
原文出处:http://www.ibm.com/developerworks/library/os-spark/ Spark 是一种与 Hadoop 相似的开源集群计算环境,但是两者之间还存在一些不同 ...
- no newline at the end of file
[no newline at the end of file] 修复这个警告,在文件结尾回车一下就行了. 这么规定的初衷是,为了每一行都要以换行结束. 因为行尾的/表示连接下一行,如果一个文件最后一 ...
- HTML5样式、链接和表格
-------------------siwuxie095 HTML5 样式 1.标签 <style> 标签:样式定义 <link> 标签:资源引用 2.属性 rel:用于指定 ...
- Android and iOS 判断是那个系统访问。
<!-- 如果是安卓就加载. --> <neq name="Think.server.HTTP_USER_AGENT|strstr='Android'" valu ...