学习 Kylin(三):Cube 构建

完成 Cube 定义之后,此时的 Cube 状态是 DISABLED,需要对 Cube 进行构建,计算各个维度下的指标数据,才可以被查询引擎使用。

源码版本:2.3.1

构建步骤

源码 org.apache.kylin.engine.mr.BatchCubingJobBuilder2

public CubingJob build() {  
    logger.info("MR_V2 new job to BUILD segment " + seg);

    final CubingJob result = CubingJob.createBuildJob(seg, submitter, config);
    final String jobId = result.getId();
    final String cuboidRootPath = getCuboidRootPath(jobId);

    // 阶段一:创建 Hive 平表(Flat Table),物化查询表中的 Hive 视图
    inputSide.addStepPhase1_CreateFlatTable(result);

    // 阶段二:构建字典
    result.addTask(createFactDistinctColumnsStep(jobId));

    if (isEnableUHCDictStep()) {
        result.addTask(createBuildUHCDictStep(jobId));
    }

    result.addTask(createBuildDictionaryStep(jobId));
    result.addTask(createSaveStatisticsStep(jobId));
    outputSide.addStepPhase2_BuildDictionary(result);

    // 阶段三:构建 Cube
    addLayerCubingSteps(result, jobId, cuboidRootPath); // layer cubing, only selected algorithm will execute
    addInMemCubingSteps(result, jobId, cuboidRootPath); // inmem cubing, only selected algorithm will execute
    outputSide.addStepPhase3_BuildCube(result);

    // 阶段四:更新元数据,清理
    result.addTask(createUpdateCubeInfoAfterBuildStep(jobId));
    inputSide.addStepPhase4_Cleanup(result);
    outputSide.addStepPhase4_Cleanup(result);

    return result;
}

由上可知,Cube 构建可分为四个阶段:

  • 创建 Hive 平表,物化查询表中的 Hive 视图
  • 构建字典
  • 构建 Cube
  • 更新元数据,清理

阶段一:创建 Hive 平表(Flat Table),物化查询表中的 Hive 视图

这一阶段的主要任务是预计算连接运算符,把事实表和维度表连接为一张大表,也称为平表。这部分工作可通过调用数据源接口来完成,因为数据源一般有现成的计算表连接方法,高效且方便,没有必要在计算引擎中重复实现。

第一步:创建 Hive 平表:

首先,初始化

然后,创建平表

最后,事实表连接维度表并插入到平表

源码:org.apache.kylin.job.JoinedFlatTable

第二步:物化查询表中的 Hive 视图

判断如果查询表是 Hive 视图,则物化查询表

提示:

默认数据源使用 Hive,而 Hive 默认的执行引擎为 MR,可以修改配置 kylin.source.hive.enable-sparksql-for-table-opstrue,使用 Spark SQL 进行优化。

阶段二:构建字典

创建字典由三个子任务完成,有 MR 引擎完成,分别是抽取列值、创建字典和保存统计信息。是否使用字典是构建引擎的选择,使用字典的好处是很好的数据压缩率,可降低存储空间,同时也提升了存储读取的速度。缺点是构建字典需要较多的内存资源,创建维度基数超过千万的容易造成内存溢出。虽然可以通过调换外部存储来解决,但也是以降低速度为代价。

Kylin 使用字典编码(Dictionary-coder)对 Cube 中的维度值进行压缩:

  • 通过存储 ID 值代替真实值来压缩 Cube 大小
  • 维度值到 ID 的双向映射
  • 维护了顺序从而加快区间查询
  • 减少了内存和存储的占用

Kylin 字典使用了前缀树(Trie)数据结构实现

参考:http://kylin.apache.org/blog/2015/08/13/kylin-dictionary/

第一步:事实表列去重字典

启动一个 MR 任务,完成三项工作:

  • 使用 HyperLogLog 算法统计 Cuboid 行数
  • 对维度列进行字典编码生成字典文件

第二步:UHC 字典(需手动启动)

UHC 是 Ultra High Cardinality (超高基数维度)的缩写

第三步:构建字典

加载字典文件到缓存

第四步:保存统计指标

阶段三:构建 Cube

第二版 MR 引擎带有两种构建 Cube 的算法,分别是逐层(Layer)构建和快速(In-Mem)构建。对于不同的数据分布来说他们各有优劣,区别主要在于数据通过网络 shuffle 的策略不同。由于网络是大多数 Hadoop 集群的瓶颈,因此不同的 shuffle 策略往往决定了构建的速度。两种算法的子任务将被全部加入工作流计划中,在执行时会根据数据源的统计信息自动选择一种算法,未被选择的算法的子任务将被自动跳过。在构建 Cube 的最后还将调用存储引擎接口,存储引擎负责将计算完的 Cube 放入存储。

第一步:构建基础的 Cuboid

第二步:构建 N 维的 Cuboid

第三步:将 Cuboid 文件转换为 HFile 导入 HFile

提示:

修改 kylin.cube.algorithmauto,根据统计信息自动选择构建 Cube 算法。

阶段四:更新元数据,清理

最后阶段,Cube 已经构建完毕,MR 引擎将首先添加子任务更新 Cube 元数据,然后分别调用数据源接口和存储接口对临时数据进行清理。

参考

  • 《Apache Kylin 权威指南》, 机械工业出版社, Apache Kylin 核心团队
  • Optimize Cube Build