问题1:hive的数据是否能够平滑迁移到iceberg来 ?

是可以的,现在iceberg提供了spark拓展工具,这个工具可以完全不挪到原始的hive orc/parquet文件,直接生成iceberg的metadata,然后就可以拿到一个iceberg表格。原来访问hive的spark、hive、presto作业,切换到iceberg表上访问完全兼容,之前sql怎么写的,现在sql依然可以复用。
只需要把表名改成iceberg的表名即可。

iceberg设计的初衷就是要在云上完全替换掉hive,经过netflix、apple、linkedin、adobe这些公司的场景磨练,无缝替换hive上云应该是iceberg当前release的场景里面最核心的场景。

问题2:hive数仓迁移到iceberg数据湖架构的核心收益是什么?

1. 近实时数仓

把仓或湖的某个表按照访问模式拆分成三种:

  • 入湖/仓:一般是通过spark或者flink把kafka或者fs内的数据导入到湖/仓。
  • 批作业分析湖/仓的数据:就是用当前表的数据跑spark/hive/presto/hive作业,做聚合或者统计,呈现报表。
  • 出湖/仓:一般是把湖/仓中的数据,通过批作业做一些过滤、清洗、轻度聚合,导出到下游表。

image.png

相比hive数仓,Iceberg数据湖的近实时优势主要体现在以下几个方面:

  • 入湖

之前入hive数仓至少以30分钟为周期入一次,现在入iceberg可以5分钟入一次。本质上在于iceberg对metadata管理可以实现更好的扩展性,它去掉了对中心化的hive-metastore的依赖,直接把metadata托管在oss对象存储之上,不存在大表扩展的问题。

有人可能会担心5分钟一次入湖,会产生大量的iceberg manfiests文件,虽然入湖影响不大,但会严重影响【分析】部分的效率和性能。这个问题是可解的,iceberg提供了data文件的合并,以及metadata的合并,按照5分钟频次入湖,那么上一个小时的data和metadata文件就可以合并了。在这种机制下,拉长时间点来看,5分钟入一次iceberg湖并不会比1小时入一次iceberg湖多一个数量级的metadata文件。对【分析】部分的影响比较可控。

此外,iceberg原生提供的ACID机制,使得用户在隔离【入湖】对【分析】的影响时减轻了心智负担和开发工作量。之前入hive数仓,写入作业先写到临时文件,最后再一次性move多个临时文件到hive数仓,完成hive数据的可见性,move多个文件的过程难以保证原子性,【入湖】作业就有较大概率影响【分析】作业。所以入hive数仓的常规做法是每次写入都写一个新的partition,然后query的时候指定partition范围只查询老的分区。这套机制在天级别的离线系统里面,基本上没啥问题。一旦做到5分钟级别的数据实效性,数据分析工程师的心智负担大大增加,他怎么知道我现在应该指定什么分区范围呢?有了iceberg的ACID隔离机制,就不存在这个问题,最近5分钟的数据通过txn commit了,查询就能看见,否则就看不见,不存在看一半数据的问题。

  • 分析

分析作业的近实时优势,一方面是由iceberg入湖近实时优势带来的,数据入湖入的早,看到的数据就越实时;另一方面来自存储端对查询端的性能优化:

对hive表来说,一次查询需要先去hive-metastore里面把partition列表拿下来,然后去文件系统上依次list每个partition的orc/parquet文件,再依次把每个orc/parquet文件的统计信息跟query的filter对比,看看哪些文件在里面,最终剩下候选文件。去做数据扫描。

对iceberg表来说,每一个data文件的所有列的max-min、count等统计信息都记录在manifests中。一个批作业query过来,不需要做任何metastore扫描和文件系统list,直接把manifests load进来按照filter过滤orc/parquet文件。最终去扫描候选文件的数据即可。iceberg的这种实现,对大表场景查询性能有数倍差距

其他在data skipping方面,iceberg目前filter已经可以下推到row-group的粒度了,借助bloom filter来加速等值查询等优化应该也能很快release。另外,iceberg对orc/parquet的向量化reader支持也相对比较完善。总结来说,iceberg在分析侧性能优化这块,做的工作比hive要好很多,也就使得【分析】作业即使扫描大体量的数据也能拿到更实时的结果。

除此之外,我们iceberg还在开发设计一下功能,未来将对细分场景的分析性能做更好的优化:

  1. secondary index 功能。这个功能将使用更丰富的index来实现查询性能的优化。
  2. z-order 来实现多维度排序查询的需求,从而实现更好效率的data skipping。

总之,iceberg在分析侧投入的开发资源还是非常丰富的,可能仅次于周边生态系统的对接。这种分析侧的优化,使得对同一份数据,查询的实效性比hive存储要好很多。

  • 出湖

在常规的数仓体系里,用户会把数据划分成 ods -> dwd -> dws 三层。一份数据会通过Hive T+1的离线调度方式在三层间流转。由于上文所说的 hive 在【入仓】方面的不足,使得出湖/出仓在下游流转过程中,呈现联机延迟。比如ods层,1天入一次仓,那么第二天用户拿着仓里面的数据可能跑了一天入dwd层,第3天可能又跑了一天入dws层。极端情况下,数据落到dws层时已经过去4天了。

Iceberg做到5分钟级别的入湖实效性,使得下游可以在第5分钟开始作业调度,跑出结果落到dwd层。最终落到dws层的数据实效性要远远优于hive数仓。

2. 数据变更

Hive数仓一开始就是为分析静态数据而设计的,而实际上在仓/湖上面做数据变更是业务非常常见的一个需求。非常基础的几个case:

  • 仓/湖里面的某个表要加个字段;
  • 仓/湖里面的某个表要改一下partition方式,比如把partition粒度从天级别变成15分钟级别。这在hive里面是比较难受的,要把整个表的数据整个重新导一遍,非常耗时。
  • 跑个 INSERT OVERWIRTE 来覆盖指定partition里面的数据。Hive由于缺乏acid语义,又非常容易碰到读脏数据的问题,这些都非常难受。

高阶一些的case:

  • 要跑个批作业去订正仓里面的一部分错误数据。Hive虽然实现了这个场景,但问题应该不少,这个场景需要放在ACID表中跑,而Hive ACID表本身就有不少问题。
  • 近实时地导入cdc数据或者upsert stream到仓/湖中,实现近实时分析。这是Hudi的场景,本质上是因为Hive做不了,所以才会出来Hudi。

上面列举的这些数据变更的问题,都是Apache Iceberg已经解决或者正在解决的问题。比如上面所有的基础case,apache iceberg都已经解决的非常好了;高级的case,是apache iceberg v2正在解决的问题,接下来的社区版本里面都将在湖中很好的解决这几个高阶的case。

更多的一些细节方面,可以参考以下这个PPT以及《Apache Iceberg Format V2资料阅读》。

Flink和Iceberg如何解决数据入湖面临的挑战.pdf