我们将深入探讨数据环境中开放表格式的历史和演变。我们将探讨导致它们成立的挑战、定义它们的关键创新以及它们对行业的影响。
通过了解从传统数据库管理系统到现代开放表格格式的旅程,我们可以更好地了解数据技术的现状并预测未来趋势。
1.传统表管理系统
以二维表格格式呈现信息一直是显示结构化数据的最基本和通用的方法,可以追溯到数千年之前。
数据库表的现代概念随着关系数据库的发明而出现,受到 E.F. Codd于 1970 年发表的关于关系模型的论文的启发。
从那时起,表格格式一直是关系数据库管理系统(如开创性的 System R)中管理和处理结构化数据的主要抽象。
1.1.表格格式抽象
数据表是逻辑数据集,是存储在磁盘上的物理数据文件的抽象层,提供统一的二维记录表格视图。存储引擎将来自数据集的各种对象的记录组合在一起,并将它们作为一个或多个逻辑表呈现给最终用户。
这种逻辑表表示提供了解耦和隐藏数据的物理特性的优势,从而允许在不影响用户的情况下发展、优化和修改物理实现细节。
1.2.关系表格式
在大数据时代和 2000 年代中期 Apache Hadoop 出现之前,传统的数据库管理系统 (DBMS) 坚持整体架构设计。架构如下图所示:
此体系结构由多个高度互连和紧密耦合的层组成,每个层专用于数据库运行所必需的特定功能,但所有组件都组合在一起以形成一个统一的系统。特别是存储层,它管理数据持久性的物理方面。
此结构的核心是 Storage Engine。此组件充当最低抽象级别,监督磁盘上数据的物理组织和管理。事务管理、并发控制、索引管理和恢复等关键任务也由存储引擎处理。
至关重要的是,查询层和表示层与复杂的存储层隔离运行。数据在读取和写入操作期间遍历这些层,每个层都有自己的抽象。这种封装意味着数据的物理布局和存储格式对外部系统保持隐藏。
传统数据库采用与其特定实施紧密集成的专有存储格式,不符合开放表格格式 (OTF) 的概念。
1.3.传统 DBMS 架构存在的缺陷
许多人会争辩说,这实际上根本不是一个糟糕的设计。毕竟,普通用户不应该关心、了解甚至改变底层物理层的实现方式,因为他们可能会做出灾难性的事情!此外,还应用了大量的技术专长,将互连组件集成到复杂系统中。
考虑到软件设计最佳实践,这是一个有效的论点,因为该设计完全概括了管理它的复杂性,但权衡是这种封闭和紧密耦合的设计阻碍了互操作性、可移植性和开放协作,无法基于开放标准构建可扩展的创新系统。
所以,引出了开放表格式。
1.4.开放表格式定义
拥有高度可互操作、可移植、开放和可扩展的数据系统,并且仍然能够封装管理低级任务的复杂性。
2.第一代开放表格式——Hive
2006 年发生了大数据革命,当 Apache Hadoop 项目从 Yahoo 诞生时,数据环境发生了翻天覆地的变化。
一个重大的架构突破是存储和计算的解耦。
这种基本的架构变化允许在部署在经济实惠的商用硬件上的 HDFS 分布式文件系统上以常见的半结构化文本格式(如 CSV 和 JSON)或二进制格式(如 Avro、Parquet 和 ORC)存储大量数据。
数据可以像文件一样存储在本地文件系统上,并使用所选的分布式处理框架(如 MapReduce、Pig、Hive、Impala 和 Presto)进行处理。
企业第一次可以以他们喜欢的开放格式存储大量数据,并针对各种工作负载利用不同的计算引擎,从而实现大规模分析。对于那些习惯于不灵活、昂贵、整体式存储系统和专有数据仓库的人来说,这是一个游戏规则改变者。
真正的突破是对数据的逻辑视图和如何使用数据与实际存储数据的物理现实分开。
工程师们很欣赏 Hadoop 的灵活性,但他们渴望熟悉的 SQL 和关系数据库固有的二维表格式。
为了弥合这一差距,Facebook(现为 Meta)发起了 Hive 项目,Facebook 是早期且有影响力的 Hadoop 采用者 。目标是将传统关系数据库中熟悉的 SQL 和表格结构引入 Hadoop 和 HDFS 生态系统。
一个关键的区别是它的新架构方法:构建在解耦的物理层之上,利用存储在 HDFS 分布式文件系统上的开放数据格式。
这就是Hadoop 上的 Open Table Architecture
2.1.列式二进制文件格式的演变
另一个关键的进步是开发了高效的列式开放文件格式。这始于 RCFiles,这是 Apache Hive 项目的第一代列式二进制序列化框架。
随后的创新包括 Apache ORC 作为 RCFile 的改进版本(于 2013 年发布)和 Apache Parquet(Twitter 和 Cloudera 的联合成果,也于 2013 年发布)。
这些新的开放文件格式极大地增强了 Hadoop 上基于 OLAP 的分析工作负载的性能,为直接在数据湖上构建 OLAP 存储引擎奠定了基础。
从那时起,ORC 和 Parquet 已成为管理数据湖上静态数据的事实标准开放文件格式,Parquet 越来越受欢迎,并在生态系统中得到更广泛的采用和支持。
2.2.面向目录的表格格式
将数据视为分布式文件系统(如 HDFS,即数据湖)中的表的最基本方法涉及将表投影到包含不可变数据文件和可能的子目录以进行分区的目录中。
核心原则是在目录树中组织数据文件。从本质上讲,表只是在目录级别跟踪的文件集合,可由各种工具和计算引擎访问。
需要注意的重要因素是,这种架构本质上与物理文件系统布局相关联,依靠文件和目录操作进行数据管理。自 Hadoop 诞生以来,这一直是在数据湖中存储数据的标准做法。
基于目录的分区允许根据事件或处理日期等属性来组织文件。Schema 信息可以嵌入到数据文件中,也可以由 Schema 注册表在外部进行管理。
由于表分区表示为子目录,因此查询引擎有责任解析和扫描表示为子目录的每个分区,以便在查询规划阶段识别相关数据文件。
这意味着物理分区与表级别的逻辑分区紧密耦合,具有自己的约束。
2.3.Hive 表格式
对于所提供的存储模型,可以说 Apache Hive 是一种面向目录的表格式,它依赖于底层文件系统的 API 将文件映射到表和分区。因此,Hive 在很大程度上受到分布式文件系统中数据的物理布局的影响。
Hive 使用自己的分区方案,使用字段名称和值创建分区目录。它在称为 Metastore 的关系数据库中管理架构、分区和其他元数据。
到目前为止,Hive + Hadoop 的重大转变 是:与传统的整体式数据库不同,Hadoop 和 Hive 的解耦方法允许其他查询和处理引擎使用 Hive 引擎的元数据在 HDFS 上处理相同的数据。
2.3.1.Hive 样式的分区方案
这导致了新数据架构与传统 DBMS 系统之间的另一个主要区别:传统系统将数据和元数据(如表定义)紧密绑定,而新范例将这些组件分开。
这种解耦提供了极大的灵活性。数据可以在没有元数据的情况下摄取到数据湖中,并且多个处理系统可以独立地将自己的元数据或表定义分配给相同的数据。
2.3.2.Hive 元数据存储
此外,集中式架构注册表(例如 Hive Metastore,它已成为事实上的标准)允许任何处理引擎使用熟悉的 SQL 或 python 语言以及 Spark、Presto 和 Trino 等其他计算框架,以结构化表格格式与数据进行交互。
通过访问注册表中的表元数据,查询引擎可以确定底层存储层上的文件位置,了解分区方案,并执行自己的读取和写入操作。
2.4.Hive表格式的缺点和限制
从 2006 年到 2016 年的近十年时间里,Hive 一直是 Hadoop 平台上最流行的表格格式。Uber、Facebook 和 Netflix 等科技巨头严重依赖 Hive 来管理他们的数据。
然而随着这些公司扩展其数据平台,他们遇到了 Hive 无法充分解决的重大可扩展性和数据管理挑战。
2.4.1.面向目录的表格格式的挑战和缺点
主要有以下挑战和缺点
(1)高度依赖底层文件系统
此架构严重依赖底层存储系统来提供基本保证,如原子性、并发控制和冲突解决。缺少这些属性的文件系统(例如 Amazon S3 缺少原子重命名)需要自定义解决方法。
(2)文件列表性能
目录和文件列表操作可能会成为性能瓶颈,尤其是在执行大规模查询时。像 S3 这样的云对象存储对目录样式的列表操作施加了很大的限制。每个 LIST 请求最多返回 1000 个对象,因此需要多个顺序请求,由于延迟和速率限制,这可能会很慢。这会显著影响处理大型数据集时的性能。
(3)查询规划开销
在 HDFS 等分布式文件系统上,由于需要详尽的文件和分区列表,因此查询规划可能非常耗时。这在处理大量文件和分区时尤其明显。
2.4.2.使用 Hive 样式分区的缺点和挑战
主要有以下挑战和缺点
(1)分区爆炸
紧密耦合的物理和逻辑分区可能会导致过度分区,尤其是对于高基数分区列(如 year/month/day)。这会导致过多的小文件、增加的元数据开销以及由于需要扫描大量分区而导致的查询规划速度变慢。过度分区对 Hive、Spark 和 Presto 等 MPP 引擎尤其有害,因为它们难以进行查询规划和扫描大量小分区。
假设一个 Hive 表按 20 个省份分区,后跟 year=/month=/day=/hour= 分区。这样的表将在 6 年内累积超过 100 万个分区。
(2)云效应
由于 API 调用限制,云数据湖加剧了过度分区问题。扫描许多分区和文件的作业经常会遇到限制,从而导致性能严重下降。
(3)小文件太多
不正确的分区方案可能会创建大量小文件,对不同层[8]产生负面影响,减慢查询和作业规划速度,重新分区需要重写整个数据集,这是一个昂贵且耗时的过程。
(4)性能不佳
如果不为跳过数据指定分区键,对 Hive 样式的基于目录的分区的查询可能会很慢,尤其是在具有较深分区层次结构的情况下。意外的全表扫描变得很常见,导致查询执行效率低下且耗时长。
(5)意外的高成本查询
意外的全表扫描可能会导致启动大型查询和作业。在管理 Hadoop 平台的这些年里,不得不多次向最终用户解释为什么由于在查询规划阶段扫描大量分区,他们的简单 Hive 查询需要很长时间才能运行。
2.4.3.使用 External Metastore 的缺点
除了上述缺点之外,使用外部 Metastore 的 Hive 样式表还带来了更多挑战:
(1)性能瓶颈
Hive 和 Impala 都依赖于外部元数据存储(通常是 MySQL 或 PostgreSQL 等关系数据库),由于表操作的频繁通信,这可能会成为性能瓶颈。
(2)元数据性能可扩展性
随着数据量和分区数量的增长,Metastore 的负担越来越重,导致查询规划缓慢、负载增加和潜在的内存不足错误。社区已广泛记录和解决了这些问题。许多公司(如 Airbnb)在[9]升级平台之前都遇到了 Metastore 性能挑战。
(3)单点故障
Metastore 表示单点故障。崩溃或不可用可能会导致大范围的查询失败。实施高可用性对于减少停机时间至关重要。
(4)网络延迟
查询引擎与外部 Metastore 以及底层关系数据库之间的网络延迟可能会影响整体性能。
(5)低效的统计信息管理
Hive 依赖于存储在 Metastore 中的分区级列统计信息,随着时间的推移,性能可能会受到影响。具有大量列和分区的宽表会积累大量统计数据,从而减慢查询计划的速度并影响表重命名等 DDL 命令。
2.2.Hive 事务表
Hive ACID 功能是将结构化存储保证,特别是 ACID 事务(原子、一致、隔离、持久)引入不可变数据湖领域的首次尝试。
此功能在 Hive 版本 3 (2016) 中发布,通过提供更强大的一致性保证(如跨分区原子性和隔离),标志着重大飞跃。此外,它还通过 upsert 功能改进了对数据湖上可变数据的管理。
但是将 ACID 添加到 Hive 并没有解决根本问题,因为:Hive ACID 表仍然植根于面向目录的方法,依靠单独的元数据存储来管理底层 Data Lake Storage 层中的表级信息。
人们曾多次尝试将 Hive ACID 集成到更广泛的数据生态系统中。Hortonworks 开发了 Hive Warehouse Connector,使 Spark 能够读取 Hive 事务表,最初依赖于 Hive LLAP 组件。
Cloudera 后来在 2020 年推出了 Spark Direct Reader 模式,允许在不依赖 Hive LLAP 的情况下直接访问文件系统。
尽管做出了这些努力,但Hive ACID 并没有引起社区的想象力,因为它的底层设计限制未能得到广泛采用。对读取和写入 Hive ACID 表的支持在整个生态系统中仍然不一致,许多著名的工具(如 Presto)提供的支持有限或没有支持。
3.第二代开放表格式——Hudi等
上一代表格格式中发现的主要问题:
(1)物理分区与数据的逻辑分区方案之间的紧密耦合。
(2)在查询规划阶段,严重依赖文件系统或对象存储 API 来列出文件和目录。
(3)依赖外部元数据存储来维护表级信息,例如架构、分区和列级统计信息。
(4)缺少对记录级 upsert、merge 和 delete 的支持。
(5)缺少 ACID 和事务属性。
为了解决前三个问题,我们必须考虑如何将分区方案与物理文件布局解耦,最大限度地减少对文件和分区列表的文件系统 API 调用,并消除对外部元数据存储的依赖。
我们需要一个能够有效存储有关数据、分区和文件列表的元数据的数据结构。此结构必须快速、可扩展且自包含,不依赖于外部系统。
通过利用日志文件,我们可以将所有元数据修改视为不可变的、按顺序排序的事件。这与事件溯源数据建模范式一致,在事件溯源数据建模范式中,我们在与数据一起存储的事务日志中捕获分区和文件级别的状态变化。
文件和分区成为元数据层跟踪日志中所有状态更改的记录单位。在此设计中,元数据日志是元数据层的一等公民。
3.1.构建一个简单的面向日志的表
我们将构建一个简单的面向日志的元数据表格式,用于捕获文件系统和存储级状态更改。
为了捕获存储级别或文件系统状态更改,我们需要考虑两个主要的文件系统对象,即文件和目录(即分区),可能发生以下事件:
重命名可以被视为两个事件,一个删除和一个添加。
3.2.管理元数据更新
鉴于 HDFS 或对象存储等数据湖存储系统的不可变性,元数据日志无法持续追加。相反数据操作操作(例如,新数据摄取)产生的每次更新都需要创建新的元数据文件。
为了维护序列并促进表状态重建,可以在基本元数据目录中按顺序命名和组织这些元数据日志。
为了重建当前表状态,元数据目录中元数据日志的顺序,以及日志中的 Timestamp 字段,可以用作物理或逻辑时钟,它可以为重放元数据事件提供强大的顺序排序语义。
查询引擎可以按顺序扫描事件日志以重放所有元数据状态更改事件,以便重建表的当前快照视图。
3.3.日志压缩
大型数据集上的频繁数据更新可能会导致元数据日志文件激增,因为每次更改都需要新的日志条目。
随着时间的推移,在状态重建期间列出和处理这些文件的开销可能会成为性能瓶颈,从而抵消分离元数据管理的好处。
为了缓解这种情况,压缩过程可以将单个日志文件合并到一个整合文件中,从而删除过时的记录,例如被取代的 add 和 remove 事件。但是对于时间旅行和回滚功能,这些过时的事件必须保留指定的时间段。
通过定期执行后台压缩作业,我们可以生成快照日志,其中包含截至特定时间点的所有基本状态更改。
在上面的示例中, 已为顺序日志文件生成快照日志snapshot_000004.log 000001.log 到 000004.log 包含该点之前的所有元数据事务。要获取当前表快照视图,需要扫描最新的快照文件以及任何其他新的增量日志文件,现在这更加优化和高效。
我们成功设计了一种面向日志的基础表格式,通过使用简单、不可变的事务日志来管理表元数据和数据文件,从而满足我们的初始要求。
这种方法是 Apache Hudi、Delta Lake 和 Apache Iceberg 等现代开放表格式的基础。
本质上:现代开放表格式通过基于日志的元数据层在不可变数据文件之上提供可变表抽象层,提供类似数据库的功能,例如 ACID 合规性、更新插入、表版本控制和审计。
这种架构转变标志着与以前的表差异巨大,它消除了对底层存储系统元数据 API 的严重依赖,这是大规模数据湖中的潜在性能瓶颈。
通过抽象物理文件布局并跟踪元数据层内文件级别的表状态(包括分区),这些格式使用面向日志的元数据层将逻辑和物理数据组织解耦,如下所示。
3.4.行业采用
过去几年见证了下一代开放表格式在各种数据工具和平台上的广泛采用和集成。
所有主要的开放式表格格式都获得了关注和普及,而主要由将这些产品作为托管服务提供的 SaaS 供应商进行的市场主导地位的激烈竞争一直在进行。
主要云提供商也接受了三大格式中的一种或全部,Microsoft 完全致力于将 Delta Lake 用于其最新的 OneLake 和 Microsoft Fabric 分析平台,而 Google 则采用 Iceberg 作为其 BigLake 平台的主要表格格式。领先的 Hadoop 供应商 Cloudera 也围绕 Apache Iceberg 构建了其开放数据湖仓一体解决方案。
Presto、Trino、Flink 和 Spark 等著名的开源计算引擎 现在支持读取和写入这些开放表格式。此外,包括 Snowflake、BigQuery 和 Redshift 在内的主要 MPP 和云数据仓库供应商已通过外部表功能整合了支持。
除了这些工具和平台之外,许多公司还公开记录了他们向开放表格格式的迁移。
4.第三代开放表格式——统一表格式
开放式表格式的发展呈新趋势:跨表互操作性。
这一令人兴奋的开发旨在创建一种统一且通用的 Open Table 格式,该格式可在后台与所有主要的现有格式无缝协作。
目前,格式之间的转换需要元数据转换和数据文件复制。但是,由于这些格式共享一个基础,并且通常使用 Parquet 作为默认序列化格式,因此存在重要的互操作性机会。
统一的元数据层承诺提供跨所有主要开放表格式读取和写入数据的统一方法。不同的读取器和写入器将利用此层与所需的格式进行交互,无需手动转换特定于格式的元数据或数据文件。
4.1.最新架构
LinkedIn 工程师率先在 2022 年推出的 OpenHouse 中率先尝试了统一表 API。OpenHouse 基于 Apache Iceberg 构建, 通过与 Spark 无缝集成的 RESTful Table Service 提供了一个简化的界面,用于与表交互,无论其底层格式如何。
虽然 OpenHouse 是一项艰巨的工作,但它缺乏全面的互操作性和格式转换功能。此外,与其他已经获得巨大关注的新兴项目相比,它在 2024 年的开源来得相对较晚,尤其是在 Databricks、Microsoft 和 Google 等大型科技公司支持后续项目的情况下。
Apache XTable(以前称为 OneTable)由 OneHouse 于 2023 年推出,它提供了一个轻量级抽象层,用于使用架构、分区详细信息和列统计信息的通用模型为任何支持的格式生成元数据。在元数据布局方面,XTable 在元数据层中并排存储每种格式的元数据。
XTable 使用主表格式的最新快照,并为目标格式生成其他元数据。使用者可以使用主要格式或目标格式来读取和写入,并获得相同的表数据一致视图。
Databricks 于 2023 年 推出了 Delta UniForm。Delta UniForm 会自动为 Delta Lake 和 Iceberg 表生成元数据,同时维护共享 Parquet 数据文件的单个副本。需要注意的是,主要由 Databricks 赞助的 UniForm 似乎专注于使用 Delta Lake 作为主要格式,同时使外部应用程序和查询引擎能够读取其他格式。
4.2.架构比较
LinkedIn 的 OpenHouse 项目提供的更多的是简单的控制,而不是统一的表格格式层。
将 Apache XTable 与 Delta Uniform 进行比较,XTable 采用了更广泛的方法,旨在实现完全互操作性,并允许用户混合和匹配来自不同格式的读/写功能,而不管选择哪种主要格式。
例如,XTable 可以支持将数据增量摄取到 Hudi 表中(利用其效率),同时允许 Trino、Snowflake 或 BigQuery 等查询引擎使用 Iceberg 格式读取数据。
话虽如此我们仍处于统一表格格式 API 开发的早期阶段。看看他们在未来几个月的进展将令人兴奋。
5.数据湖仓一体
数据湖仓一体的含义:数据湖仓一体代表统一的下一代数据架构,它将数据湖的成本效益、可扩展性、灵活性和开放性与通常与数据仓库相关的性能、事务保证和治理功能相结合。
这个定义听起来与开放表格格式所代表的非常相似!这是因为 Lakehouse 基础的基础是利用开放表格式直接在低成本云存储上实施 ACID、审计、版本控制和索引,以弥合这两种传统上不同的数据管理范式之间的差距。
从本质上讲,数据湖仓一体使组织能够将数据湖存储视为传统数据仓库,反之亦然。它们提供数据湖的灵活性和解耦架构,允许以开放格式存储非结构化和半结构化数据,并使用各种计算引擎,并结合数据仓库的性能、事务功能和完整的 CRUD 操作特征。
这一愿景最初是由 SQL-on-Hadoop 工具追求的,旨在将数据仓库引入 Hadoop 平台,但直到最近随着数据领域的进步才完全实现。
5.1.非开放数据与开放数据湖仓一体
区分一般的 “数据湖仓一体” 和 “开放数据湖仓一体” 至关重要。
虽然 AWS 和 Google 等顶级云供应商经常将其以数据仓库为中心的平台标记为数据湖仓一体,但它们的定义更广泛。
他们强调数据仓库存储半结构化数据、支持 Spark 等外部工作负载、启用 ML 模型训练和查询开放数据文件的能力,所有这些特征传统上都与数据湖相关。这些平台通常还具有解耦的存储和计算架构。
大约在 2020 年至 2021 年,亚马逊开始推广湖仓一体概念[15],该概念由 在新的 RA3 托管存储上实施的 Amazon Redshift 数据仓库以及 Redshift Spectrum 组成,然后 Databricks 等其他供应商和一般数据社区更广泛地采用“湖仓一体”一词作为数据仓库的新方法。
Google 同样推广了其分析湖仓一体架构,在 2023 年发布的白皮书[16]中进行了概述,为使用 BigQuery 作为首选或开放的 Apache Iceberg 和 BigLake 平台构建统一分析湖仓一体提供了蓝图。
另一方面,开放数据湖仓一体主要利用开放表格式来管理低成本数据湖存储上的数据。这种架构促进了更高的互操作性和灵活性,使组织能够为每个作业或工作负载选择最佳的计算和处理引擎。
通过消除跨系统复制和移动数据的需要,开放数据湖仓一体可确保所有数据保持其原始的开放格式,作为单一事实来源。
开放数据湖仓一体架构如下图所示:
Databricks、Microsoft OneLake、OneHouse、Dremio 和 Cloudera 等供应商已将自己定位为云上托管开放数据湖仓一体平台的提供商。