Apache Iceberg 是一种开源的表格格式,专为在数据湖中存储大规模分析数据而设计。它与多种大数据生态系统组件高度兼容,相较于传统的 Hive 表格格式,Iceberg 在设计上提供了更高的性能和更好的可扩展性。它支持 ACID 事务、Schema 演化、数据版本化、隐式分区和跨引擎兼容性等功能,使其特别适合处理数据密集型的大数据分析任务。
然而,Iceberg 的使用也伴随着一些挑战,如较高的上手难度、后台维护需求、性能优化和治理策略等。这些挑战可能增加系统的复杂性并带来性能上的考验,因此用户需要根据自身的业务需求和场景进行仔细的权衡和调整。
在本篇文章中,我们将详细介绍 Iceberg 的架构和特性,深入探讨其优势与面临的挑战。最后,我们将分享几个 StarRocks + Iceberg 的解决方案,希望通过用户的真实场景,帮助大家更好地使用 StarRocks 构建湖仓分析新范式。
Hive 尽管在大数据生态系统中被广泛采用,但它仍旧存在一些设计上的局限性,从而导致在处理大型数据集时存在一些限制:
尽管 Hive 作为早期的数据仓库解决方案发挥了重要作用,但它的性能和灵活性存在一些固有限制,这些限制在实际应用中对数据处理和分析工作构成了挑战。随着数据湖三剑客 Iceberg、Hudi、Delta Lake 为代表的新一代数据湖表格式问世,用户开始从这些限制中解放出来,数据湖的应用也迎来了新一轮的快速发展。据数据湖领域的权威专家预测,尽管目前 Delta Lake 在市场占有率方面领先,但在未来三年内,Apache Iceberg 有望逐渐超越,成为占据最大市场份额的数据湖格式。这一预测不仅基于 Iceberg 技术上的优势,也反映了业界对其发展潜力的普遍认可。值得注意的是,Snowflake 最近发布的新版本中采用了 Iceberg 的表格式来存储和管理一部分源数据,这进一步证实了 Iceberg 在数据湖领域日益增强的影响力和强劲的发展势头。
The Latest Data Trends and Predictions for 2024 by Dremio
https://www.youtube.com/watch?v=bULVEsss7y
Apache Iceberg 的架构设计分为三个主要层次:
- 数据层(Data Layer):这一层次包含了实际的数据文件,如 Parquet 和 ORC 格式的文件,它们是存储数据的物理载体。
- 元数据层(Metadata Layer):Iceberg 的元数据层是多级的,负责存储表的结构和数据文件的索引信息。
- Catalog 层:这一层存储了指向元数据文件位置的指针,是元数据的索引。Iceberg 提供了多种 Catalog 实现,例如:
- HadoopCatalog:直接使用 Hadoop 文件系统目录来管理表信息。
HiveCatalog:将表的元数据存储在 Hive Metastore 中,便于与现有的 Hive 生态系统集成。用户还可以利用 Iceberg 的 API 开发自定义的 Catalog 实现,以便将元数据存储在其他所需位置。
- Iceberg 允许用户根据时间戳的不同粒度(如年、月、日或小时)组织数据分区。
- 使用语法如
CREATE TABLE catalog.MyTable (..., ts TIMESTAMP) PARTITIONED BY days(ts)
可实现基于天的时间戳分区,新写入的数据自动归入相应分区。
Schema Evolution(Schema 演化)Partition Evolution(分区演化)Row-level update: COW & MOR- COW(Copy on Write):V1 表格式支持,数据更新时复制原始数据,在副本上应用更改。
- MOR(Merge on Read):V2 表格式支持,引入位置删除文件和等值删除文件,实现逻辑删除,数据读取时反映最新状态。
- 位置删除记录需要删除的数据行的位置信息,适合数据不频繁变更的场景。
- 等值删除保存要删除数据的值,读取时通过比较执行删除。
我们可以看出 Iceberg 提供了强大的功能和灵活性,但同时也要求用户投入相应的技术努力来实现最佳的系统管理和性能。
在使用 Apache Iceberg 进行数据查询时,面临的一个主要挑战是高延迟问题。由于 Iceberg 能够记录文件级别的详细信息,扫描整个表以进行数据查询可能需要较长的时间。尤其是在使用如 Amazon S3 这样的对象存储服务时,尽管已经实现了输入文件的缓存机制,但解析操作依然耗时。
解析操作的耗时主要由于 Iceberg 的清单文件(manifest files)通常被高比例压缩。例如,一个典型的 8MB 大小的清单文件,在解压后可能占用高达 300MB 的内存空间。使用 C++ 进行读取时,即使在最佳情况下,解析时间也可能达到 1 秒左右。
公开案例表明,在元数据较大(big metadata)场景下,使用 Iceberg 进行数据规划(planner)可能需要长达 50 分钟,而花费十几分钟完成查询是常见的情况。此外,清单文件的内存占用问题不容忽视,尤其是在处理大型数据集时。
在消费清单文件的过程中,尽管 Iceberg 采用了多线程流控制机制,但如果单个查询进行了优化,如实施了特定的缓存策略,可能会降低消费速率,从而对查询性能产生负面影响。如果 Iceberg 处理任务的并发较高,这种影响可能被放大,很容易产生 GC 停顿时间比实际任务执行时间更长。
总的来说,尽管 Iceberg 提供了强大的数据湖功能,但在数据导入和查询性能方面,用户需要采取适当的优化措施,以应对高延迟和资源占用的挑战。
StarRocks,最适合 Iceberg 的查询加速神器
StarRocks 不仅能高效的分析本地存储的数据,也可以作为计算引擎直接分析数据湖中的数据。用户可以通过 StarRocks 提供的 External Catalog,轻松查询存储在 Iceberg 上的数据,无需进行数据迁移。目前,StarRocks 已经支持了读取 Iceberg v1、v2(包含 position delete 和 equality delete)表,同时也支持向 Iceberg 表中写入数据。
我们知道一条查询依赖元数据的获取与解析、执行计划的生成与高效的执行。针对查询 Iceberg 的场景,StarRocks 不仅可以利用到 StarRocks 原生的向量化引擎、CBO 优化器等能力,StarRocks 也对湖上查询做了很多额外优化。
对于外部托管的数据,StarRocks 需要从外部拉取元数据并进行解析。这里面有两个性能瓶颈点:拉取(远端文件 I/O)和解析(decompress+decode)。针对元数据拉取,StarRocks 的元数据缓存可以避免重复拉取,造成不必要的 I/O 浪费。
然而如上文所说,在元数据本身就是大数据量的情况下,性能瓶颈已经不在远端 I/O 上,而在解析上了。因为 Iceberg Manifest 文件是 Avro 这类行存格式,且解析 Avro 严重依赖 Iceberg Master 节点的 CPU,导致在文件较多的时候造成 Master 节点压力激增,从而大幅度增加 Plan 耗时。而一个 Manifest 文件里可能包含几万个 data file,却只有几个 file 被查询涉及,解析的“性价比”就更低了。一个直观的想法是,能否使用 StarRocks 原生的 MPP 架构来加速这个过程呢?
由此,StarRocks 3.3 版本开始支持了 Iceberg 的分布式 Job Plan,即元数据文件通过 StarRocks 的分布式框架来进行并行读取,并且在每个节点完成 Manifest 的读取与过滤,并统一返回给 FE 来执行后续的流程。这一流程是无状态的,整个流程不仅对用户没有感知,对内的处理流程也更加轻量级,没有任何持久化的维护工作。
此时,另一个直观的想法是,既然解析消耗如此大,那是否可以缓存解析后的 Manifest 呢?由此,从 3.3 版本开始,StarRocks 也支持了反序列化的 Manifest Cache。当有查询命中历史文件时,StarRocks 会直接去从反序列化的 Manifest 中获取信息,降低了解析的开销。
这一架构的升级,不仅突破了 Iceberg SDK 的限制,还充分利用到了 StarRocks 的分布式框架与 Pipeline 执行引擎,可以在高并发、元数据量大(big metadata)、表文件数量大的情况下突破 Iceberg 的原生限制,提升查询性能,降低对 Iceberg 数据治理与优化的负担。
CBO 生成一个好的查询规划需要有大量的信息辅助,从而能够针对各类情况(如数据倾斜、关联表的数据情况不同等)生成代价最小的方案。
由此,StarRocks 3.2 版本开始支持了收集外部表(包括 Hive 与 Iceberg)的统计信息,3.3 版本开始支持了直方图统计信息,并且增加了对复杂类型 Struct 子列的统计信息收集。这些信息能够为 StarRocks 生成更高效的执行计划提供重要输入。
数据湖上采用的往往都是主流的开放格式,如 Parquet、ORC、Textfile 等。StarRocks 针对这几类格式进行了持续且细致的优化。一方面尽可能利用外部格式原生的信息优势、降低数据扫描量;另一方面优化策略,尽可能降低远端 I/O 开销。具体优化例如尽可能利用 Parquet、ORC 的 footer 与字典信息加速查询、动态自适应的 I/O 合并等,我们会在后面的文章中详尽解释。
虽然主流的开放格式因其更好的性能与更广泛的兼容性被用户广泛选择,但数据湖场景中经常还是会有一些其他格式的历史文件需要被访问,StarRocks 也通过扩展更通用的 Connector 框架来逐步支持,目前已经支持了 Avro、SequenceFile 以及 RCFile 的读取。
湖仓架构不仅保证了 Single Source of Truth,在架构上更加经济、易扩展。然而湖上查询始终是访问远端存储上的开放格式。相比于查询 StarRocks 内表,一方面 I/O 开销较大,另一方面无法应用 StarRocks 的原生数据格式优化。为了给湖上用户提供如同数仓一般的查询体验,StarRocks 开发了两大杀器:
Data Cache 是一种将热数据缓存至本地的技术。它由查询触发,将查询涉及到的远端数据切分为 Block 级别的数据块并拉到本地缓存。如下一次其他查询也命中同样的数据 Block,则可以直接从本地读取,无需访问远端存储,降低 I/O 开销。Data Cache 采用内存和磁盘两级缓存,且不会引入数据一致性问题,对终端查询用户没有感知。在全部命中 Cache 的情况下,StarRocks 可以提供类似内表的查询体验。
Data Cache 在很大程度上缓解了远程 I/O 开销,尤其在远端存储(如 HDFS)较为抖动的时候,Data Cache 可以缓解外部环境对查询性能的影响,提供更加稳定的查询表现。
在计算逻辑较为复杂、性能以及并发要求更高的场景下,StarRocks 的物化视图可以给用户更好的性能保障。
物化视图可以通过预先定义查询的方式,定期将外部数据加工并刷入 StarRocks 内部中,无需用户管理导入 Pipeline;进入 StarRocks 的物化视图和内表一样,可以享受 StarRocks 内部格式的加速手段,如 Colocate Join、各类 index 等;在查询时,物化视图支持智能的查询改写,这意味着用户无需更改查询,StarRocks 会智能路由至已经物化好的结果上,享受原地性能提升。
目前,基于 Iceberg 的物化视图除了丰富的改写能力以外,已经可以做到感知分区变更,从而进行分区级别的增量刷新,降低刷新开销。
StarRocks 不仅支持了读取 Iceberg v1、v2(pos-delete 以及 eq-delete)格式的表,同时还支持回写 Iceberg。从而无论是数据回湖统一,还是对湖上数据进行轻量级的加工,都可以轻松地借助 StarRocks 完成。- 数据落湖:在一些对实效性要求较高的场景,实时数据可以先进入 StarRocks 完成数据的落地与更新,对外提供秒级的数据可见性。一定时间后,可以写回 Iceberg 进行数据资产的统一管理,完成 single source of truth。
- 数据加工:配合 StarRocks 算子落盘与各类资源隔离功能,可以通过 StarRocks对 Iceberg 数据进行轻量级加工与回刷。
不仅如此,腾讯游戏的同学也基于 Iceberg 回写的能力在研发降冷功能,能够提供更加透明无感知的降冷以及查询体验。会在未来的版本中发布与介绍。
StarRocks + Iceberg 用户最佳实践
腾讯微信基于 StarRocks + Iceberg 的湖仓一体实践
微信数据分析面临的挑战包含了海量数据的处理、要求极速的查询响应(TP90 在 5 秒内),以及需要实现计算和存储的统一
- 湖仓一体架构已在微信的多个业务场景中实施,如视频号直播、微信键盘等,集群规模达数百台机器,数据接入量近千亿。
- 在直播业务场景中,数据开发任务数减半,存储成本降低 65% 以上,离线任务产出时间缩短两小时。
关于 StarRocks
Linux 基金会项目 StarRocks 是新一代极速全场景 MPP 数据库,遵循 Apache 2.0 开源协议。
面世三年来,StarRocks 致力于帮助企业构建极速统一的湖仓分析新范式,是实现数字化转型和降本增效的关键基础设施。目前,全球 380 家以上市值超过 70 亿元人民币的顶尖企业选择用 StarRocks 来构建新一代数据分析能力,这些企业包括腾讯、携程、平安银行、中原银行、中信建投、招商证券、大润发、百草味、顺丰、京东物流、TCL、OPPO 等。StarRocks 也已经和全球云计算领导者亚马逊云、阿里云、腾讯云等达成战略合作关系。StarRocks 全球开源社区也正飞速成长。目前,StarRocks 的 GitHub star 数已达 8000,吸引了超过 350 位贡献者和数十家国内外行业头部企业参与共建,用户社区也有过万人的规模。凭借其卓越的表现,StarRocks 荣获了全球著名科技媒体 InfoWorld 颁发的 2023 BOSSIE Award 最佳开源软件奖项。