华为云 MRS 基于 Apache Hudi 极致查询优化的探索实践

背景湖仓一体(LakeHouse)是一种新的开放式架构,它结合了数据湖和数据仓库的最佳元素,是当下大数据领域的重要发展方向 。华为云早在2020年就开始着手相关技术的预研,并落地在华为云 FusionInsight MRS智能数据湖解决方案中 。
目前主流的三大数据湖组件 Apache Hudi、Iceberg、Delta各有优点,业界也在不断探索选择适合自己的方案 。
华为湖仓一体架构核心基座是 Apache Hudi,所有入湖数据通过 Apache Hudi 承载,对外通过 HetuEngine(Presto增强版)引擎承担一站式SQL分析角色,因此如何更好的结合 Presto 和 Hudi 使其查询效率接近专业的分布式数仓意义重大 。查询性能优化是个很大的课题,包括索引、数据布局、预聚合、统计信息、引擎 Runtime优化等等 。
本文主要介绍 Presto 如何更好的利用 Hudi 的数据布局、索引信息来加速点查性能 。预聚合和统计信息我们将在后续分享 。
数据布局优化大数据分析的点查场景一般都会带有过滤条件,对于这种类型查询,如果目标结果集很小,理论上我们可以通过一定手段在读取表数据时大量跳过不相干数据,只读取很小的数据集,进而显著的提升查询效率 。我们可以把上述技术称之为 DataSkipping 。好的数据布局可以使相关数据更加紧凑(当然小文件问题也一并处理掉了)是实现 DataSkipping的关键一步 。日常工作中合理设置分区字段、数据排序都属于数据布局优化 。当前主流的查询引擎 Presto/Spark 都可以对Parquet文件做 Rowgroup 级别过滤,最新版本甚至支持 Page 级别的过滤;选取合适的数据布局方式可以使引擎在读取上述文件可以利用列的统计信息轻易过滤掉大量 Rowgroup/Page,进而减少IO 。那么是不是 DataSkipping仅仅依赖数据布局就好了?其实不然 。上述过滤还是要打开表里每一个文件才能完成过滤,因此过滤效果有限,数据布局优化配合 FileSkipping才能更好的发挥效果 。当我们完成数据布局后,对每个文件的相关列收集统计信息,下图给个简单的示例,数据经过排序后写入表中生成三个文件,指定点查 where a < 10下图可以清楚的看出 a < 10的结果集只存在于 parquet1文件中,parquet2/parquet3 中 a 的最小值都比10大,显然不可能存在结果集,所以直接裁剪掉 parquet2parquet3即可 。
FileminValue_amaxValue_aparquet10999parquet210002000parquet320013000这就是一个简单 FileSkippingFileSkipping的目的在于尽最大可能裁剪掉不需要的文件,减少扫描IO,实现 FileSkipping有很多种方式,例如 min-max统计信息过滤、BloomFilter、Bitmap、二级索引等等,每种方式都各有优缺点,其中 min-max 统计信息过滤最为常见,也是 Hudi/Iceberg/DeltaLake 默认提供的实现方式 。
Apache Hudi核心能力1. ClusteringHudi早在 0.7.0 版本就已经提供了 Clustering 优化数据布局,0.10.0 版本随着 Z-Order/Hilbert高阶聚类算法加入,Hudi的数据布局优化日趋强大,Hudi 当前提供以下三种不同的聚类方式,针对不同的点查场景,可以根据具体的过滤条件选择不同的策略
方式使用场景额外补充说明Order只有一个过滤列如:where a > 10 Clustering时只需按a排序即可Order排序具有一定特殊性,当指定多列排序时,最终排序结果以第一列为准,其他列很难本有序 。PS:主要这并不代表Order不能用于多列排序 。以下场景可以直接用Order多列排序:1. 排序列都是低基字段;2. 只有一个高基字段,将该高基字段放到排序列最后Z-Order多个过滤字段,一般2到4个,超过4个效果要打折扣,Z-Order简单来说是一种均匀排序的思想,经过该算法参与排序的所有列都会基本有序,不会出现Order那种只排第一列的情况多列排序效果绝大数情况下比Order要好,但是构建速度相比Order较慢 。PS: 对于2列低基字段排序,选择Order比较合适Hilbert和Z-Order一样,不过排序效果更好,但构建速度更慢同上关于 Z-Order、Hilbert 具体原理可以查阅相关Wiki,https://en.wikipedia.org/wiki/Z-order 本文不再详细赘述 。

经验总结扩展阅读