Hudi内核分析之虚拟键(Virtual Keys)

总览

Apache Hudi根据不同的表类型、配置参数来帮助您构建和管理数据湖,以满足每个人的需要。Hudi添加了每个记录的元数据字段,如_hoodie_record_key_hoodie_partition path_hoodie_commit_time,它有多种用途。它们有助于避免在合并、压缩和其他表操作期间重新计算记录键、分区路径,还有助于支持记录级增量查询(与仅跟踪文件的其他表格式相比)。此外,即使给定表的键字段在其生命周期内发生了更改,它也通过确保执行唯一的键约束来确保数据质量。但是对于不需要这些好处或关键更改非常少的简单用例,来自社区的反复要求之一是利用现有的字段,而不是添加额外的元字段。

虚拟键支持

Hudi现在支持虚拟键,其中Hudi元字段可以根据需要从数据字段计算。目前,元字段只计算一次,并作为记录元数据存储,并在各种操作中重用。如果不需要增量查询支持,他们可以开始利用Hudi的Virtual key支持,并继续使用Hudi来构建和管理他们的数据湖,以减少每个记录元数据带来的存储开销。

相关配置

可以使用下面的配置为给定的表启用虚拟键。当设置hoodie.population.meta.fields=false时,Hudi将为相应的表使用虚拟键。此配置的默认值为true,这意味着所有元字段将在默认情况下添加。

一旦启用了虚拟键,就不能对给定的hudi表禁用它,因为已经存储的记录可能没有填充元字段。但如果你有一个旧版本的hudi的现有表,虚拟键可以启用。w.r.t虚拟键支持的另一个约束是,给定表的键生成器属性不能在给定hudi表的生命周期中更改。在这个模型中,用户还分担确保表中键的唯一性的责任。例如,如果您将记录键配置为指向field_5的几批写操作,然后切换到field_10,那么Hudi就不能保证键的唯一性,因为较早的写操作可能对field_10有重复。

使用虚拟键时,每次需要(合并、压缩、MOR快照读取)时都必须重新计算键。因此,我们为Copy-On-Write表上的所有内置键生成器支持虚拟键。支持Merge-On-Read表上的所有键生成器将需要从基日志和增量日志中读取所有字段,从而牺牲核心柱查询性能,这对用户来说是非常昂贵的。因此,我们目前只支持简单的键生成器(默认键生成器,其中记录键和分区路径都引用现有字段)。

CopyOnWrite(COW)表支持的键生成器

SimpleKeyGenerator, ComplexKeyGenerator, CustomKeyGenerator, TimestampBasedKeyGenerator and NonPartitionedKeyGenerator.

MergeOnRead(MOR)表支持的键生成器

SimpleKeyGenerator

支持的索引类型

初始版本只支持SIMPLE以及GOLBAL_SIMPLE,后续计划支持其他像BLOOM等索引。

支持的操作

除了增量查询外,所有现有的特性都支持带有虚拟键的hudi表。这意味着,清理、归档、元数据表、clustering等可以为一个启用虚拟键的hudi表启用。因此,如果您希望这样做,您可以仅仅使用Hudi作为事务性表格式,并与所有出色的表服务运行时和平台服务一起使用,而不会产生与支持增量数据处理相关的任何开销。

样例展示

如之前所述,需要设置hoodie.population.meta.fields=false来开启虚拟键,接下来看一下开启和未开启虚拟键的区别。

以下是常规hudi表的一些记录示例(禁用虚拟键)

+--------------------+--------------------------------------+--------------------------------------+---------+---------+-------------------+
|_hoodie_commit_time |           _hoodie_record_key         |        _hoodie_partition_path        |  rider  | driver  |        fare       |
+--------------------+--------------------------------------+--------------------------------------+---------+---------+-------------------+
|   20210825154123   | eb7819f1-6f04-429d-8371-df77620b9527 | americas/united_states/san_francisco |rider-284|driver-284|98.3428192817987  |
|   20210825154123   | 37ea44f1-fda7-4ec4-84de-f43f5b5a4d84 | americas/united_states/san_francisco |rider-213|driver-213|19.179139106643607|
|   20210825154123   | aa601d6b-7cc5-4b82-9687-675d0081616e | americas/united_states/san_francisco |rider-213|driver-213|93.56018115236618 |
|   20210825154123   | 494bc080-881c-48be-8f8a-8f1739781816 | americas/united_states/san_francisco |rider-284|driver-284|90.9053809533154  |
|   20210825154123   | 09573277-e1c1-4cdd-9b45-57176f184d4d | americas/united_states/san_francisco |rider-284|driver-284|49.527694252432056|
|   20210825154123   | c9b055ed-cd28-4397-9704-93da8b2e601f | americas/brazil/sao_paulo            |rider-213|driver-213|43.4923811219014  |
|   20210825154123   | e707355a-b8c0-432d-a80f-723b93dc13a8 | americas/brazil/sao_paulo            |rider-284|driver-284|63.72504913279929 |
|   20210825154123   | d3c39c9e-d128-497a-bf3e-368882f45c28 | americas/brazil/sao_paulo            |rider-284|driver-284|91.99515909032544 |
|   20210825154123   | 159441b0-545b-460a-b671-7cc2d509f47b | asia/india/chennai                   |rider-284|driver-284|9.384124531808036 |
|   20210825154123   | 16031faf-ad8d-4968-90ff-16cead211d3c | asia/india/chennai                   |rider-284|driver-284|90.25710109008239 |
+--------------------+--------------------------------------+--------------------------------------+---------+----------+------------------+

下面是一些启用了虚拟键的hudi表的示例记录。

+--------------------+------------------------+-------------------------+---------+---------+-------------------+
|_hoodie_commit_time |    _hoodie_record_key  |  _hoodie_partition_path |  rider  | driver  |        fare       |
+--------------------+------------------------+-------------------------+---------+---------+-------------------+
|        null        |            null        |          null           |rider-284|driver-284|98.3428192817987  |
|        null        |            null        |          null           |rider-213|driver-213|19.179139106643607|
|        null        |            null        |          null           |rider-213|driver-213|93.56018115236618 |
|        null        |            null        |          null           |rider-284|driver-284|90.9053809533154  |
|        null        |            null        |          null           |rider-284|driver-284|49.527694252432056|
|        null        |            null        |          null           |rider-213|driver-213|43.4923811219014  |
|        null        |            null        |          null           |rider-284|driver-284|63.72504913279929 |
|        null        |            null        |          null           |rider-284|driver-284|91.99515909032544 |
|        null        |            null        |          null           |rider-284|driver-284|9.384124531808036 |
|        null        |            null        |          null           |rider-284|driver-284|90.25710109008239 |
+--------------------+------------------------+-------------------------+---------+----------+------------------+

如您所见,存储中的所有元字段都是空的,但所有用户字段保持不变,类似于普通表。

增量查询

由于在虚拟键启用后hudi不维护任何表的元数据(如在记录级别提交时间),所以是不支持增量查询的。如果你做了增量查询,则会出现如下异常:

scala> val tripsIncrementalDF = spark.read.format("hudi").
     |   option(QUERY_TYPE_OPT_KEY, QUERY_TYPE_INCREMENTAL_OPT_VAL).
     |   option(BEGIN_INSTANTTIME_OPT_KEY, "20210827180901").load(basePath)
org.apache.hudi.exception.HoodieException: Incremental queries are not supported when meta fields are disabled
  at org.apache.hudi.IncrementalRelation.<init>(IncrementalRelation.scala:69)
  at org.apache.hudi.DefaultSource.createRelation(DefaultSource.scala:120)
  at org.apache.hudi.DefaultSource.createRelation(DefaultSource.scala:67)
  at org.apache.spark.sql.execution.datasources.DataSource.resolveRelation(DataSource.scala:344)
  at org.apache.spark.sql.DataFrameReader.loadV1Source(DataFrameReader.scala:297)
  at org.apache.spark.sql.DataFrameReader.$anonfun$load$2(DataFrameReader.scala:286)
  at scala.Option.getOrElse(Option.scala:189)
  at org.apache.spark.sql.DataFrameReader.load(DataFrameReader.scala:286)
  at org.apache.spark.sql.DataFrameReader.load(DataFrameReader.scala:232)
  ... 61 elided

总结

希望这个博客对你学习Apache Hudi的另一个特性有用。如果你对Hudi感兴趣并想要投稿,请点击这里

0 0 投票数
文章评分

本文为从大数据到人工智能博主「xiaozhch5」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://lrting.top/backend/2026/

(0)
上一篇 2021-11-12 19:28
下一篇 2021-11-12 19:32

相关推荐

订阅评论
提醒
guest

0 评论
内联反馈
查看所有评论
0
希望看到您的想法,请您发表评论x