暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

hudi 、iceberg 、paimon 比较

sg1234 2024-04-20
5070

Hudi 高效处理数据的奥秘

Hudi 文件布局

Hudi 文件布局是指其在文件系统中组织数据的方式,主要包括以下几种文件类型:

  1. Base File: 存储经过合并后的数据,通常采用列式存储格式(如 Parquet),以便于高效查询。Base File 可能包含多个版本的数据,但通过内部结构(如版本标识符)区分不同版本。

  2. Log File: 在某些合并策略(如 Merge-On-Read, MOR)下,用来记录每次增量写入的操作日志,包括插入、更新和删除的动作。Log File 允许在不立即更新 Base File 的情况下快速进行增量写入,延后合并过程至读取时。

  3. Ingestion File: 初始写入或增量写入时生成的小文件,通常在后续的合并作业中会被合并到 Base File 中。

  4. Compacted File: 经过合并操作后的文件,可能是多个 Ingestion File 合并的结果,或者是 Base File 与其他文件合并后的产物。Compaction 过程旨在减少文件数量、优化存储空间和查询性能。

图片

图片

列式存储

采用列式存储格式(如 Parquet),仅加载查询所需的列,减少 I/O 和内存开销,且易于进行压缩和编码优化。

LSM (Log-Structured Merge Tree)

虽然 Hudi 不直接使用传统的 LSM 架构,但其 MOR(Merge-On-Read)模式借鉴了 LSM 的思想。在 MOR 中,数据首先被写入 Log File(类似于 LSM 的 MemTable),然后在后台异步地进行合并(类似于 LSM 的 Compaction)。这样设计的好处在于:

  • 写放大降低:更新和删除操作只需追加写入 Log File,而非直接修改 Base File,减少了磁盘写入次数。

  • 读放大可控:查询时需要同时读取 Base File 和 Log File,但通过高效的合并策略和索引机制可以控制读取的 Log File 数量,从而限制读放大程度。

MOR (Merge-On-Read) 与 COW (Copy-On-Write)

  1. MOR (Merge-On-Read):

  • 写入:新数据或更新数据追加写入 Log File,不立即更新 Base File。

  • 读取:查询时同时读取 Base File 和相关 Log File,合并结果返回给查询引擎。合并过程在内存中进行,通常利用索引来加速。

  • 优点:写入速度快,延迟低,尤其适用于高写入频率、低查询频率或查询延迟要求不严格的场景。

  • 缺点:读取时可能需要合并多个文件,存在一定的读取延迟和资源消耗。

  • 图片

  1. COW (Copy-On-Write):

  • 写入:新数据或更新数据触发 Base File 的部分或全部复制,生成新的 Base File 版本。

  • 读取:查询时直接读取最新的 Base File。

  • 优点:读取性能好,无需合并,提供近实时查询能力。

  • 缺点:写入成本较高,尤其是频繁更新时可能导致大量的数据复制和存储空间增长。

  • 图片

  • 图片
    图片
    图片

多模态索引

Hudi通过索引机制提供高效的Upsert操作,该机制会将一个RecordKey+PartitionPath组合的方式作为唯一标识映射到一个文件ID,而且这个唯一标识和文件组/文件ID之间的映射自记录被写入文件组开始就不会再改变。

Hudi 提供了多模态索引机制以加速查询:

  1. Bloom Filter Index: 用于快速判断某个键是否存在于数据集中,减少不必要的文件扫描。

  2. Global/Partition Index: 提供对数据全局或分区范围内的快速查找,尤其适用于点查或范围查询。

  3. Min-Max Index: 记录每个分区或文件中数据的最小和最大值,支持数据Skipping(跳过无关数据块)。

  4. Inverted Index: 用于高效处理基于值的查询,如全文搜索、标签匹配等。

1)、全局索引:在全表的所有分区范围下强制要求键保持唯一,即确保对给定的键有且只有一个对应的记录。

2)、非全局索引:仅在表的某一个分区内强制要求键保持唯一,它依靠写入器为同一个记录的更删提供一致的分区路。

Data Skipping

Data Skipping 是一种查询优化技术,通过利用索引信息提前过滤掉无关数据,减少查询过程中实际读取的数据量。在 Hudi 中,主要通过以下方式实现:

  • Min-Max Index: 查询时利用 Min-Max 索引快速判断文件内数据是否与查询条件相交,如果完全不相交,则跳过该文件。

  • Column Statistics: 对数值型或日期型字段统计平均值、标准差、分位数等统计信息,辅助查询优化器做出更准确的成本估算,决定是否跳过部分数据。

Sort & ZOrder

排序和 ZOrder 编码是进一步优化查询性能的手段:

  • Sort: 对数据按照一个或多个键进行排序,有利于范围查询和聚合操作,同时可以提高压缩效率。在 Hudi 中,可以在写入时对数据进行排序,或者在合并过程中对数据进行重新排序。

  • ZOrder: 一种多维排序技术,将多列数据交织在一起形成一个新的排序键。相比单一列排序,ZOrder 更能有效地减少范围查询时需要读取的数据块数量,尤其在多维分析场景下效果显著。Hudi 支持在 Compaction 过程中应用 ZOrder,对数据进行重新布局。

总结来说,Hudi 通过精心设计的文件布局、借鉴 LSM 思想的 MOR 模式、多模态索引、Data Skipping 技术以及 Sort 和 ZOrder 编码,实现了高效的数据写入、存储管理和查询性能。这些特性使其在大数据湖环境中能够很好地支持大规模、高并发、实时更新的数据处理需求。

iceberg 高效处理的奥秘

文件布局
data files(数据文件):

数据文件是Apache Iceberg表真实存储数据的文件,一般是在表的数据存储目录的data目录下,如果我们的文件格式选择的是parquet,那么文件是以“.parquet”结尾,例如:

00000-0-root_20211212192602_8036d31b-9598-4e30-8e67-ce6c39f034da-job_1639237002345_0025-00001.parquet 就是一个数据文件。

Iceberg每次更新会产生多个数据文件(data files)。
Snapshot(表快照):
快照代表一张表在某个时刻的状态。每个快照里面会列出表在某个时刻的所有 data files 列表。data files是存储在不同的manifest files里面,manifest files是存储在一个Manifest list文件里面,而一个Manifest list文件代表一个快照。
Manifest list(清单列表):
manifest list是一个元数据文件,它列出构建表快照(Snapshot)的清单(Manifest file)。这个元数据文件中存储的是Manifest file列表,每个Manifest file占据一行。每行中存储了Manifest file的路径、其存储的数据文件(data files)的分区范围,增加了几个数文件、删除了几个数据文件等信息,这些信息可以用来在查询时提供过滤,加快速度。
Manifest file(清单文件):
Manifest file也是一个元数据文件,它列出组成快照(snapshot)的数据文件(data files)的列表信息。每行都是每个数据文件的详细描述,包括数据文件的状态、文件路径、分区信息、列级别的统计信息(比如每列的最大最小值、空值数等)、文件的大小以及文件里面数据行数等信息。其中列级别的统计信息可以在扫描表数据时过滤掉不必要的文件。
Manifest file是以avro格式进行存储的,以“.avro”后缀结尾,例如:8138fce4-40f7-41d7-82a5-922274d2abba-m0.avro。
图片

列式存储

Iceberg 支持使用列式存储格式(如 Parquet 和 ORC),这是其高效性的核心之一。列式存储将数据按列而非按行进行组织,每个列单独存储并压缩。这种格式有以下优点:

  • 高效查询:只需读取查询涉及的列,显著减少 I/O 操作,尤其适用于仅需访问少量列的分析查询。

  • 高效压缩:由于同一列内的数据类型相同,可以采用更高效的压缩算法,降低存储空间占用。

  • 向量化执行:与现代查询引擎的向量化执行模式天然契合,能批量处理大量数据,提高CPU利用率。

LSM (Log-Structured Merge Tree)

虽然 Iceberg 并不直接使用 LSM 树作为底层存储结构,但其某些特性(如数据文件合并与 compaction)借鉴了 LSM 的思想。LSM 树是一种高效处理大量写入和更新的数据结构,通过将写入操作先记录在内存中的 memtable,随后定期合并到磁盘上的有序段(SSTable),并通过 compaction 过程合并段并清除无效数据。

Compaction

在 Iceberg 中,compaction 是一种数据管理操作,用于合并小文件、删除无效数据、更新元数据统计信息,并优化数据布局。Compaction 可以是手动触发或根据策略自动进行,有助于减少文件数量、提升查询性能,并保持数据集的整体健康状态。

DataSkipping

Iceberg 支持 DataSkipping 算法,允许查询引擎跳过无关数据块。这通常通过在元数据中存储数据文件的统计信息(如 min/max 值)实现,查询时可以利用这些信息进行谓词下推,避免读取不符合查询条件的数据。

Sorted Tables

Iceberg 支持创建排序表(Sorted Tables),其中数据在某个或某几个列上预排序。排序表对于涉及范围查询、窗口函数或者需要特定顺序的数据处理任务非常有利,可以进一步优化查询性能。

分区与隐藏分区(Hidden Partition)

Iceberg支持分区来加快数据查询。在Iceberg中设置分区后,可以在写入数据时将相似的行分组,在查询时加快查询速度。Iceberg中可以按照年、月、日和小时粒度划分时间戳组织分区。

在Hive中也支持分区,但是要想使分区能加快查询速度,需要在写SQL时指定对应的分区条件过滤数据,在Iceberg中写SQL查询时不需要再SQL中特别指定分区过滤条件,Iceberg会自动分区,过滤掉不需要的数据。

在Iceberg中分区信息可以被隐藏起来,Iceberg的分区字段可以通过一个字段计算出来,在建表或者修改分区策略之后,新的数据会自动计算所属于的分区,在查询的时候同样不用关心表的分区是什么字段,只需要关注业务逻辑,Iceberg会自动过滤不需要的分区数据。

正是由于Iceberg的分区信息和表数据存储目录是独立的,使得Iceberg的表分区可以被修改,而且不会涉及到数据迁移。

表演化(Table Evolution)

在Hive分区表中,如果把一个按照天分区的表改成按小时分区,那么没有办法在原有表上进行修改,需要创建一个按照小时分区的表,然后把数据加载到此表中。

Iceberg支持就地表演化,可以通过SQL的方式进行表级别模式演进,例如:更改表分区布局。Iceberg进行以上操作时,代价极低,不存在读出数据重新写入或者迁移数据这种费时费力的操作。

模式演化(Schema Evolution)

Iceberg支持以下几种Schema的演化:

  • ADD:向表或者嵌套结构增加新列。

  • Drop:从表或嵌套结构中移除列。

  • Rename:重命名表中或者嵌套结构中的列。

  • Update:将复杂结构(Struct、Map<Key,Value>,list)中的基本类型扩展类型长度,比如:tinyint修改成int。

  • Reorder:改变列的顺序,也可以改变嵌套结构中字段的排序顺序

注意:

Iceberg Schema的改变只是元数据的操作改变,不会涉及到重写数据文件。Map结构类型不支持Add和Drop字段。

Iceberg保证Schema演化是没有副作用的独立操作,不会涉及到重写数据文件,具体如下:

  • 增加列时不会从另一个列中读取已存在的数据

  • 删除列或者嵌套结构中的字段时,不会改变任何其他列的值。

  • 更新列或者嵌套结构中字段时,不会改变任何其他列的值。

  • 改变列或者嵌套结构中字段顺序的时候,不会改变相关联的值。

Iceberg实现以上的原因使用唯一的id来追踪表中的每一列,当添加一个列时,会分配新的ID,因此列对应的数据不会被错误使用。

分区演化(partition Evolution)

Iceberg分区可以在现有表中更新,因为Iceberg查询流程并不和分区信息直接关联。

当我们改变一个表的分区策略时, 对应修改分区之前的数据不会改变, 依然会采用老的分区策略, 新的数据会采用新的分区策略, 也就是说同一个表会有两种分区策略, 旧数据采用旧分区策略, 新数据采用新新分区策略, 在元数据里两个分区策略相互独立,不重合.

因此,在我们写SQL进行数据查询时, 如果存在跨分区策略的情况, 则会解析成两个不同执行计划, 如Iceberg官网提供图所示:

图片

图中booking_table表2008年按月分区, 进入2009年后改为按天分区, 这两中分区策略共存于该表中。得益于Iceberg的隐藏分区(Hidden Partition), 针对上图中的SQL查询, 不需要在SQL中特别指定分区过滤条件(是按照月还是按照天), Iceberg会自动分区, 过滤掉不需要的数据。

列顺序演化(Sort Order Evolution)

Iceberg可以在一个已经存在的表上修改排序策略。修改了排序策略之后, 旧数据依旧采用老排序策略不变。往Iceberg里写数据的计算引擎总是会选择最新的排序策略, 但是当排序的代价极其高昂的时候, 就不进行排序了。

ZOrder

ZOrder(或 Z-curve Ordering)是一种空间填充曲线(Space-Filling Curve),用于将多维数据映射到一维空间,从而实现高效的多维数据索引和查询。在 Iceberg 中,ZOrder 可用于对表进行物理排序,特别是在具有多个排序键的场景下。通过应用 ZOrder,Iceberg 可以将原本分散在多个分区的数据按排序键顺序排列在同一数据文件内,从而优化涉及范围查询、窗口函数或者需要特定顺序的数据处理任务。启用 ZOrder 后,查询性能可能会显著提升,尤其是对于需要跨分区扫描的查询。

Zorder排序压缩策略使得多个排序字段时,每个字段的优先级是相等的。

Zorder排序压缩策略优点是对于多个经常使用的字段可以提升读取的性能,缺点是合并压缩的时间较长。

Delta实现的z-order和Hudi、Iceberg的实现从本质上来说都是文件间的排序采用zorder, 文件内的排序任然采用线性排序的思想。这样可以在小范围查询中(查询正好落入单个文件内)使用线性排序会有更好的性能。但是不同的是生成z-value的方式上的不同,Delta生成z-value的方式是采用映射为rangeid的办法,并未采用直接转换为二进制的办法。这种方式避免了额外操作以及多次排序,但需要更多的专家经验。另外Delta的Zorder操作需要用户手动的执行优化。

Parquet BloomFilter

BloomFilter 是一种空间效率极高的概率型数据结构,用于快速判断一个元素是否可能属于一个集合,存在一定的误判率但没有漏判。在 Iceberg 使用的 Parquet 文件格式中,可以为特定列启用 BloomFilter,以加速谓词过滤。启用 BloomFilter 后,查询引擎在处理查询条件时,可以先利用 BloomFilter 快速排除掉大部分肯定不满足条件的数据,从而减少对实际数据的读取,提高查询性能。

binPack 压缩策略

binPack算法的本质就是在我们设置压缩的目标文件大小配置后target-file-size-bytes,使用装箱算法,快速的将较小的文件写入较大的文件。

binPack算法是默认的Iceberg压缩策略的算法,也是最快的压缩策略,其不会做全局的排序,可能会在任务内做本地排序。

binPack优势是”快“,缺点是数据并没有被聚集分类起来(数据没被排序),不利于join读取等。

CALL catalog.system.rewrite_data_files(
  table => 'streamingtable',
  strategy => 'binpack',
  where => 'created_at between "2023-01-26 09:00:00" and "2023-01-26 09:59:59" ',
  options => map(
    'rewrite-job-order','bytes-asc',
    'target-file-size-bytes','1073741824',
    'max-file-group-size-bytes','10737418240',
    'partial-progress-enabled', 'true'
  )
)

MOR-Position/Equality Delete

下面介绍一下Iceberg的upsert。Upsert有两种实现方式:copy on write和merge on read。

  • copy on write:实现方式类似Spark的overwrite

  • merge on read:Iceberg对merge on read的实现是写时生成DeleteFile,在读的时候将DeleteFile应用到DataFile上

DeleteFile有两种方式:Position Delete和Equality Delete。

图片

(1)Position Delete
  • 文件里记录的是哪个文件(file_path)的第几条记录(pos)需要被删除。

  • 写Position Delete需要先读取DataFile,然后根据过滤条件判断哪些记录需要被删除,再写成Position DeleteFile。写入较慢,因为需要先进行task scan找到对应的文件,然后再写数据。

  • Spark的MOR目前只支持Position Delete。

(2)Equality Delete
  • 文件里记录的是过滤条件,写入的速度快,读的速度慢,因为并不能准确的定位到文件,可能读了很多的DataFile,但是并不一定被删除,即apply的过程较慢。

  • Flink的CDC场景记录的就是这种方式。

Parquet Vectorized Read Decimal

Iceberg的向量化读不是采用Spark读Parquet/ORC的那一套,而是基于Apache Arrow实现的。我们在跑TPCDS的时候发现Iceberg Parquet的向量化读的性能和Spark是有差距的,主要原因是在读取Decimal时差距比较大。这里我们对Decimal的向量化读做了优化,在1TB TPCDS数据集上,对store_sales表full table scan有近两倍的性能提升。

学习链接:https://www.cnblogs.com/sap-jerry/p/17701425.html
import org.apache.iceberg.Table
import org.apache.iceberg.NullOrder

val table:Table = null
table.replaceSortOrder()
.asc("user_id", NullOrder.NULLS_LAST)
.desc("user_name", NullOrder.NULLS_FIRST)
// .commit()
import org.apache.iceberg.expressions.Expressions
import org.apache.iceberg.Table

val table:Table = null

// =========Partition更新==========
table.updateSpec()
// 添加分区字段user_id,且一个分区内分桶数量为10
.addField(Expressions.bucket("user_id", 10))
// 删除分区字段country
.removeField("country")
// .commit()
CALL catalog.system.rewrite_data_files(
  table => 'iceberg_03',
  strategy => 'sort',
  sort_order => 'team ASC NULLS LAST, name ASC NULLS FIRST'
)

paimon 高效处理的奥秘

文件布局

图片

1 Snapshot Files

所有快照文件都存储在快照目录中。

快照文件是一个JSON 文件,包含有关此快照的信息,包括:

正在使用的Schema文件

包含此快照的所有更改的清单列表(manifest list)

2 Manifest Files

所有清单列表(manifest list)和清单文件(manifest file)都存储在清单(manifest)目录中。

清单列表(manifest list)是清单文件名(manifest file)的列表。

清单文件(manifest file)是包含有关LSM 数据文件和更改日志文件的文件信息。例如对应快照中创建了哪个LSM数据文件、删除了哪个文件。

3 Data Files

数据文件按分区和存储桶分组。每个存储桶目录都包含一个LSM 树及其变更日志文件。目前,Paimon 支持使用 orc(默认)、parquet 和 avro 作为数据文件格式。

4 LSM Trees

Paimon 采用 LSM 树(日志结构合并树)作为文件存储的数据结构。

4.1 Sorted Runs

LSM 树将文件组织成多个Sorted Run。Sorted Run由一个或多个数据文件组成,并且每个数据文件恰好属于一个Sorted Run。

数据文件中的记录按其主键排序。在Sorted Run中,数据文件的主键范围永远不会重叠。

图片

正如您所看到的,不同的Sorted Run可能具有重叠的主键范围,甚至可能包含相同的主键。查询LSM树时,必须合并所有Sorted Run,并且必须根据用户指定的合并引擎和每条记录的时间戳来合并具有相同主键的所有记录。

写入LSM树的新记录将首先缓存在内存中。当内存缓冲区满时,内存中的所有记录将被排序并刷新到磁盘。

4.2 Compaction

当越来越多的记录写入LSM树时,Sorted Run的数量将会增加。由于查询LSM树需要将所有Sorted Run合并起来,太多Sorted Run将导致查询性能较差,甚至内存不足。

为了限制Sorted Run的数量,我们必须偶尔将多个Sorted Run合并为一个大的Sorted Run。这个过程称为Compaction。

然而,Compaction是一个资源密集型过程,会消耗一定的CPU时间和磁盘IO,因此过于频繁的Compaction可能会导致写入速度变慢。这是查询和写入性能之间的权衡。Paimon 目前采用了类似于 Rocksdb 通用压缩的Compaction策略。

默认情况下,当Paimon将记录追加到LSM树时,它也会根据需要执行Compaction。用户还可以选择在“专用Compaction作业”中独立执行所有Compaction。

列式存储:

  • 数据布局:Paimon 采用列式存储格式,即数据按列而非按行组织在磁盘上。这种布局方式使得在进行数据分析时,只需读取查询涉及的特定列,而不是整个数据记录,从而减少了I/O操作,显著提升了查询性能,特别是在处理大量数据的聚合查询和过滤查询时。

  • 高效压缩:列式存储天然有利于数据压缩,因为同一列内的数据具有相同的类型和相似的值分布,可以使用针对特定数据类型的高效压缩算法(如Run-Length Encoding、Delta Encoding、Dictionary Encoding等),进一步减少存储空间需求,同时在解压时仍能保持较高的效率。

高效压缩:

  • 压缩算法:Paimon 应用高效的压缩算法来减少数据在存储和传输过程中的空间占用。这可能包括无损压缩(如gzip、lz4等)以及专门针对列式存储优化的压缩技术,如前面提到的列专用编码。

  • 资源节省:通过高效压缩,Paimon 不仅降低了存储成本,还减少了数据在磁盘、内存和网络之间的移动量,间接提升了整体系统的性能和效率。

DataSkipping:

  • 查询优化:Dataskip 是一种查询优化技术,通过在数据块或索引中嵌入额外的元信息(如统计摘要、布隆过滤器等),使得查询引擎能在读取数据之前快速判断该数据块是否包含查询所需的数据。如果数据块与查询无关,就可以直接跳过,避免不必要的I/O操作,显著提升查询性能。

  • 减少无效扫描:尤其是在处理大规模数据集时,数据跳过技术能够极大地减少无效数据扫描,使得系统能够专注于处理真正相关的数据,对于大数据分析和复杂查询尤为关键。

异步Compaction :

  • 写入优化:在处理大量写入操作时,Paimon 可能采用异步合并(或称为Compaction)策略,将频繁的小规模写入操作合并成较少的大规模写操作。这种策略有助于减少磁盘随机写入次数,提高写入性能和磁盘寿命。

  • 数据整理:异步合并过程还负责整理数据,如合并小文件、删除无效数据、更新索引等,以保持数据集的整洁和查询效率。由于是异步进行,不会阻塞正常的读写操作,保证了系统的响应速度和可用性。

  • LSM 这种原生异步的 Minor Compaction,它可以通过异步 Compaction 落到最下层,也可以在上层就发生一些 Minor 的 Compaction 和 Minor 的合并,这样压缩之后它可以保持 LSM 不会有太多的 level。保证了读取 merge read 的性能,且不会带来很大的写放大。

另外,Flink Sink 会自动清理过期的快照和文件,还可以配置分区的清理策略。所以整个 Paimon 提供了吞吐大的 Append 写,消耗低的局部 Compaction,全自动的清理以及有序的合并。所以它的写吞吐很大,merge read 不会太慢。

大规模实时更新

Paimon 创新的结合了 湖存储 + LSM + 列式格式 (ORC, Parquet),为湖存储带来大规模实时更新能力,Paimon 的 LSM 的文件组织结构如下:

图片

高性能更新:LSM 的 Minor Compaction,保障写入的性能和稳定性

高性能合并:LSM 的有序合并效率非常高

高性能查询:LSM 的 基本有序性,保障查询可以基于主键做文件的 Skipping

数据表局部更新和跨分区更新

在数据仓库的业务场景下,经常会用到宽表数据模型,宽表模型通常是指将业务主体相关的指标、维表、属性关联在一起的模型表,也可以泛指将多个事实表和多个维度表相关联到一起形成的宽表。

Paimon 的 Partial-Update 合并引擎可以根据相同的主键实时合并多条流,形成 Paimon 的一张大宽表,依靠 LSM 的延迟 Compaction 机制,以较低的成本完成合并。合并后的表可以提供批读和流读:

批读:在批读时,读时合并仍然可以完成 Projection Pushdown,提供高性能的查询。

流读:下游可以看到完整的、合并后的数据,而不是部分列。

传媒场景中的很多实时大宽表业务中的 Partial-Update 表只有少量数据会关联上,很多非关联上的数据是不需要的,后面会引入数据淘汰策略,淘汰掉这些数据。用 Paimon 跨分区更新能力解决分区交界出数据漂移问题

丰富的表类型

除了主键表之外,Apache Paimon还支持append-only表,提供有序的流式读取来替代消息队列。

主键表的三种核心能力:主键表更新,增量数据产生机制(Changelog Producer)数据合并机制(Merge Engine)

Read Optimized

对于主键表,这是一种 "MergeOnRead "技术。读取数据时,多层 LSM 数据会被合并,并行数量会受到数据桶数量的限制。如果想在某些情况下快速查询,但只能找到较早的数据,可以从读优化表中查询:SELECT * FROM T$ro。

但这无法保证数据的新鲜度,因此可以在写入数据时配置 "full-compaction.delta-commits",以确保读取的数据具有确定的延迟。

StarRocks 和其他 OLAP 系统将在 Paimon 0.6 的基础上发布一个版本,以大大提高读优化表的查询性能。

Z-order

在数据湖Paimon中,Z-ordering可能被用来实现以下目的:

  1. 数据布局优化:通过对存储在数据湖中的多维数据(如时空数据、地理坐标等)进行Z-order编码,可以重新组织数据的物理存储布局,使得相关数据在磁盘上相邻存储,提高数据读取的局部性,从而提升查询性能。

  2. 压缩效率提升:Z-order编码后,数据的值域分布通常更连续,利于采用更高效的压缩算法。通过压缩,Paimon可以减少存储空间需求,加速数据传输。

  3. 索引构建:基于Z-order的特性,Paimon可以构建适应Z-order编码的数据索引结构,如Z-order B-tree、Z-order R-tree、minmax等索引,这些索引可以直接支持高效的多维范围查询,避免全表扫描,大幅缩短查询响应时间。

  4. 负载均衡:在分布式数据湖环境中,Z-order编码有助于将多维数据均匀分布到不同的存储节点上,避免热点区域,确保查询和处理任务在集群中的均衡分布,提高系统整体处理能力和稳定性。

Hudi、iceberg、paimon三者对比

图片
图片


对比项

图片

图片

图片

读/写特性




ACID事物支持

支持✅

支持✅

支持✅

Copy-On-Write( 写时复制)

支持 ✅

支持✅

不支持 ❌
Paimon是LSM Tree结构

Merge-On-Read(读时合并)

支持✅

不完备 ❌

无法平衡查询性能,需要手动Compaction

不完备 ❌
读取数据时,会合并多层LSM数据,并行数会受到桶数的限制。尽管Paimon的合并性能高效,但仍然无法赶上普通的AppendOnly表。

批量加载(Bulk Load)

支持 ✅
支持Bulk Insert

不支持❌

不支持 ❌

具有记录级索引的高效合并写入

支持✅

不支持 ❌


是否可以将数据就地升级到系统中而无需重写数据

支持✅


支持 ✅
需要表迁移

不支持❌


增量查询
获取表指定时间窗口的数据

支持✅

不完备 ⚠️
目前仅支持 append 的数据

支持 ✅

Time Travel

支持✅

支持✅

支持✅

数据摄入

支持 ✅
DeltaStreamer

不支持❌

支持 ✅
支持Flink CDC导入

并发控制

支持 ✅
非阻塞表服务的OCChttps://hudi.apache.org/blog/2021/12/16/lakehouse-concurrency-control-are-we-too-optimistic/

不完备 ⚠️
仅支持OCC
https://iceberg.apache.org/spec/#overview

支持 ✅
Paimon 支持多个并发写入作业的乐观并发

Primary Key

支持✅

不支持❌

支持✅

列统计和Data SKip
查询是否可以从基于任何列的谓词的文件修剪中受益,而无需读取数据文件页脚

支持 ✅
元数据中的 Col 统计
列统计索引总计性能提升 50 倍

支持 ✅
清单中的列统计信


支持 ✅
基于索引(如minmax),过滤无关文件并提供高性能查询,支持更多索引。

基于内置函数的Data Skip

不完备⚠️
通过 col stats 索引,Hudi 可以根据列谓词和列上的顺序保留函数有效地修剪文件。

支持 ✅
Iceberg 可以将表数据转换为分区值并维护关系,同时还收集列上的统计信息

不支持❌

Partition Evolution  分区演变
(是否可以不断改变表的分区结构)

不支持 ❌
Hudi 采用了不同的方法,具有粗粒度分区和细粒度集群,可以异步演化而无需重写数据。

支持 ✅
Partition Evolution 允许您随着数据的发展而更改分区。旧数据保留在旧分区中,新数据获得新分区,它们之间的性能参差不齐

支持✅

重复数据删除

支持 ✅
Record key uniqueness

Precombine Utility Customizations

从插入中删除重复内容

不完备 ⚠️
仅支持Merge Only

支持 ✅
重复数据删除以保留最后一行、部分更新、聚合记录或第一行

表服务

文件大小调整

支持 ✅
自动调整文件大小

不完备 ⚠️
手动维护

不支持❌

Compaction

支持 ✅
管理压实

不完备 ⚠️
手动维护

支持 ✅

Dedicated Compaction




自动清理
旧版本的文件会自动从存储中删除吗?

支持 ✅
托管清洁服务

不完备 ⚠️
通过快照过期方式,来手动清理

不完备 ⚠️
通过快照过期方式,来手动指定快照过期时间

分区清理

支持 ✅

支持 ✅

支持✅

索引管理
是否支持在表中新建索引

支持 ✅
异步多模式索引子系统

不支持 ❌

支持 ✅

线性聚类

自动集群可用于性能调整、用户定义的分区器

不支持 ❌

不支持 ❌

Multidimensional Z-Order/Space Curve Clustering
多维Z-Order/空间聚类

Z-Order + Hilbert 曲线与自动异步聚类

不支持❌

不支持❌

模式演化
是否可以调整表结构

不完备 ⚠️
添加、重新排序、删除、重命名、更新的架构演变(仅限 Spark)

支持 ✅
添加、重新排序、删除、重命名、更新的架构演变

支持 ✅
添加、重新排序、删除、重命名、更新的架构演变

元数据可扩展
元数据可以根据我的数据大小进行缩放

支持 ✅
基于 Hudi MoR 的元数据表,具有 HFile 格式,查找速度加快 100 倍,像任何 Hudi 表一样进行自我管理

不完备 ⚠️
Avro Manifest 文件速度明显变慢,并且在扩展时需要维护

不完备 ⚠️
参考File layouts(实际性能没有测试)

平台支持




CLI
是否可以使用CLI管理表

支持 ✅
CLI

不支持 ❌

不支持 ❌

数据质量验证
可以定义要检查和执行的质量条件吗

支持 ✅
预提交验证器

不支持 ❌

不支持❌

Pre-commit Transformers

支持 ✅
Transformers

不支持❌

不支持 ❌

Commit 通知
提交成功后我可以收到回调通知吗

支持 ✅
提交通知

不支持 ❌

不支持 ❌

失败的提交保障措施
如何保护免受部分和失败的写入操作的影响?

支持 ✅
自动标记机制

不支持 ❌

不支持 ❌
有一致性保障措施(2PC机制)

监控

用于自动监控的 MetricsReporter

不支持 ❌

支持 ✅

Savepoint and Restore
可以保存数据快照然后将表恢复到这种形式吗?

支持 ✅

用于保存特定版本的 Savepoint 命令。

使用时间旅行版本或保存点恢复命令

不支持 ❌

不完备 ⚠️
支持flink的savepoint,在特定情况下
比如代码升级、数据更新等触发savepoint



生态系统支持




Apache Spark

Read + Write

Read + Write

Read + Write

Apache Flink

Read + Write

Read + Write

Read + Write

Presto

Read

Read + Write

Read

Trino

Read

Read + Write

Read

Hive

Read

Read + Write

Read

DBT

Read + Write

不支持 ❌

不支持 ❌

Kafka Connect

Write

不支持 ❌


Kafka

Write

不支持 ❌

不支持 ❌

Pulsar

Write

Write

不支持 ❌

Debezium

Write

Write

不支持 ❌

Kyuubi

Read + Write

Read + Write

不支持 ❌

ClickHouse

Read

不支持 ❌

不支持 ❌

Apache Impala

Read + Write

Read + Write

不支持 ❌



原本转载地址              https://mp.weixin.qq.com/s/NIpud2kbiJJNOsje0Honyw

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论