searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

hudi系列-索引机制

2023-03-28 04:36:34
103
0

1. 索引机制

hudi的索引机制是为了加速upsert/delete操作,它维护着(分区 + key)-> fileID之间的映射关系,所以可以减少对非必要base文件的合并

key是指索引key,可以是表的任意字段,在全局索引中常用主键key作为索引

1.1 索引类型

当前hudi支持以下类型的索引:

  • INMEMORY:基于内存hashmap,为全局索引
  • HBASE:基于外部存储hbase做索引,天然是全局索引
  • SIMPLE, GLOBAL_SIMPLE:简单索引,将更新的key与base文件提取的key值进行join,分为全局和非全局
  • BLOOM, GLOBAL_BLOOM:基于布隆过滤器,存在假阳性问题,分为全局和非全局
  • BUCKET:由字节跳动为了弥补bloom不足而贡献的分桶索引,非全局
  • FLINK_STATE:基于flink状态的全局索引

    1.2 全局与非全局索引

  • 全局索引:必需存在表级别的唯一的索引key,每个索引key在所有分区中都只能唯一对应一条记录(一般可以采用hoodie record key,即主键)。update/delete时查找索引的复杂度是O(表记录数),所以适合小表场景。
  • 非全局索引:索引key在分区内唯一,对索引的查询只涉及本次update/delete记录的分区,所以它复杂度为O(更删记录数),适合数据量大的分区表。

    2. 基于flink写的索引

    虽然hudi的索引类型有这么多种,但是在使用flink往hudi写时只支持两种索引方式:BUCKET和FLINK_STATE

    2.1 优化重构

    在hudi的写过程中默认会调HoodieIndex#tagLocation来查找索引批量地给记录确定位置,逻辑位于BaseWriteHelper#write中,并且将查找索引花费的时间作为本次写的统计指标保存在HoodieWriteMetadata#indexLookupDuration中。

    在流式引擎中,每一次都以批量的方式计算记录的位置会给系统造成很大压力,应该流式地去计算或者获取
    基于flink的写过程FlinkWriteHelper重载去掉了查找索引的过程:

  1. 基于BUCKET的索引方式根本就不存在一份所谓的“索引数据”,它在写到文件中前根据哈希公式进行映射
  2. 基于FLINK状态的索引方式在BucketAssignFunction中流式地对每条记录进行了处理

    2.1 索引对比

  • BUCKET:预先指定固定的分桶数(hoodie.bucket.index.num.buckets),所以记录可以按分桶字段(hoodie.bucket.index.hash.field)进行哈希计算得到所在分区的桶序号,每个桶代表一个数据文件。该索引方式的特点为,每个分区下的数据文件数固定,这样才保证可以固定(分区,索引key)->fileID之间的映射,不用花费额外的空间存储索引数据,我们需要预估每个分区的数据量以确定分桶数。
  • FLINK_STATE:以表的主键作为索引key,每个key的索引数据是一个ValueState,所以它天然是全局索引。是默认的索引方式,由于使用了flink的状态,所以使用时需要考虑状态过大给Job带来的问题,有一点需要注意的是,默认情况下状态并没有设置失效日期index.state.ttl
0条评论
0 / 1000