写点什么

大数据 -163 Apache Kylin Segment 合并实战:手动 / 自动合并、保留策略与 JDBC 示例

作者:武子康
  • 2025-11-25
    山东
  • 本文字数:3677 字

    阅读完需:约 12 分钟

大数据-163 Apache Kylin Segment 合并实战:手动/自动合并、保留策略与 JDBC 示例

TL;DR

  • 场景:Cube 被频繁增量构建导致 Segment 碎片增多、查询降速与存储膨胀。

  • 结论:低峰期用手动 MERGE 兜底;长期用 Auto Merge + Retention 阈值自动治理;删除需先 Disable 再 Delete。

  • 产出:完整操作清单、阈值策略案例、删除流程、JDBC 连接示例与错误速查卡。


版本矩阵


基本流程

在 Apache Kylin 中,手动触发 Segment 合并的步骤如下:


  • 选择要合并的 Cube 和 Segments: 进入 Kylin Web UI,选择你要操作的 Cube,进入该 Cube 的详情页面。在“Segments”标签页下,可以看到当前 Cube 的所有 Segments。选择你希望合并的 Segments。

  • 合并 Segments: 点击页面上的 “Merge Segment” 按钮。通常情况下,Kylin 会自动计算可以合并的 Segments。如果你想手动控制合并的 Segments,可以在弹出的对话框中手动选择你想合并的 Segments。

  • 配置合并任务: 配置合并任务的参数,如目标时间范围等。Kylin 会根据你选择的 Segments 的范围自动填充一些默认的值。你可以根据需求调整这些参数。

  • 启动合并任务: 完成配置后,点击 “Submit” 按钮。Kylin 将会创建一个新的合并任务(Job),该任务将在后台执行。你可以在 "Job" 页面查看任务的执行状态。

  • 监控任务状态: 在 "Job" 页面,你可以查看合并任务的日志和状态。如果任务执行成功,你会看到新的 Segment 出现在 Segments 列表中,表示合并已经完成。

  • 如果合并成功,新的合并后 Segment 会替代原来的多个 Segments,而旧的 Segments 将被 Kylin 自动清理。


需要注意的是,手动合并的操作可能会占用大量资源,因此在高负载时需要谨慎操作,并在合适的时间段执行合并任务。

手动触发合并 Segment

Kylin 提供了一种简单的机制用于控制 Cube 中 Segment 的数量:合并 Segment,在 WebGUI 中选中需要进行 Segments 合并的 Cube。

单击 Action => Merge

我们刚才分阶段进行了任务的 Build 操作,01-01、01-02、01-03、01-04 的任务,我们可以使用 Merge 来进行合并:



选中需要合并的 Segment,可以同时合并多个 Segment,但这些 Segment 必须是连续的,单击提交系统会提交一个类型为 MERGE 的构建任务,这里可以选择时间阶段,我选择的是 01-03 到 01-04:



提交任务,可以看到是一个 Merge 任务,看名字:【MERGE】,等待合并完毕:



合并完毕的结果如下图:


注意事项

  • 在 MERGE 构建结束之前,所有选中用来合并的 Segment 仍然处于可用的状态

  • 在 MERGE 类型的构建完成之前,系统将不允许提交这个 Cube 上任何类型的其他构建任务

  • 当 MERGE 构建结束的时候,系统将选中合并的 Segment 替换为新的 Segment,而被替换下的 Segment 等待将被垃圾回收和清理,以节省系统资源

删除 Segment

使用 WebUI 删除 Cube 的 Segment,这里选择 Disable 就可以删除 Segment 了:



Disable 之后,可以看到下面的:DeleteSegment 操作,就可以删除指定的 Segment 了:


自动合并

手动维护 Segment 很繁琐,人工成本高,Kylin 中是可以支持自动合并 Segment。在 Cube Designer 的 Refresh Settings 的页面中有:


  • Auto Merge Thresholds

  • Retention Thresholds


Refresh Settings 的页面:



两个设置项可以用来帮助管理 Segment 碎片,这两项设置搭配使用这两项设置可以大大减少对 Segment 进行管理的麻烦。

Auto Merge Thresholds

  • 允许用户设置几个层级的时间阈值,层级越靠后,时间阈值越大

  • 每当 Cube 中有新的 Segment 状态变为 READY 的时候,就会自动触发一次系统自动合并

合并策略

  • 尝试最大一级的时间阈值,例如:针对(7 天、28 天)层级的日志,先检查能够将连续的若干个 Segment 合并成为一个超过 28 天的大 Segment

  • 如果有个别的 Segment 的事件长度本身已经超过 28 天,系统会跳过 Segment

  • 如果满足条件的连续 Segment 还不能够累积超过 28 天,那么系统会使用下一个层级的时间戳重复寻找

案例 1 理解 Kylin 自动合并策略

  • 假设自动合并阈值设置为 7 天、28 天

  • 如果现在有 A-H 8 个连续的 Segment,它们的时间长度为 28 天(A)、7 天(B)、1 天(C)、一天(D)、一天(E)、一天(F)、一天(G)、一天(H)

  • 此时,第 9 个 Segment 加入,时间长度为 1 天


自动合并的策略为:


  • Kylin 判断时能够将连续的 Segment 合并到 28 天这个阈值,由于 Segment A 已经超过 28 天,会被排除。

  • 剩下的连续 Segment,所有时间加一起 B+C+D+E+F+G+H+I < 28 天,无法满足 28 天的阈值,则开始尝试 7 天的阈值

  • 跳过 A(28)、B(7)均超过 7 天,排除

  • 剩下的连续 Segment,所有时间加在一起 C+D+E+F+G+H+I 达到 7 天的阈值,触发合并,提交 Merge 任务,并构建一个 SegmentX(7 天)

  • 合并后,Segment 为:A(28 天)、B(7 天)、X(7 天)

  • 连续触发检查,A(28 天)跳过,B+X(7+7=14)< 28 天,不满足第一阈值,重新使用第二阈值触发

  • 跳过 B、X 尝试终止

案例 2 配置自动合并 4 天的 Segment

选中 Model,选择 Edit 进行编辑:



直接到 Refresh Setting 选项卡,将选项修改为,4 天:



后续将自动进行 Segment 的构建。

配置保留的 Segment

自动合并是将多个 Segment 合并为一个 Segment,以达到清理碎片的目的,保留 Segment 则是及时清理不再使用的 Segment。在很多场景中,只会对过去一段时间内的数据进行查询,例如:


  • 对于某个只显示过去 1 年数据的报表

  • 支持它的 Cube 其实只需要保留过去一年类的 Segment 即可

  • 由于数据在 Hive 中已经存在备份,则不需在 Kylin 中备份超过一年的类似数据


可以将 Retention Threshold 设置为 365,每当有新的 Segment 状态变为 READY 的时候,系统会检查每一个 Segment。如果它的结束时间距离最晚的一个 Segment 的结束时间已经大于等于 RetentionThreshold,那么这个 Segment 将视为无需保留,系统会自动从 Cube 中删除这个 Segment。


保留策略示意图如下所示:


使用 JDBC 连接操作 Kylin

简单介绍

  • 要将数据以可视化方式展示出来,需要使用 Kylin 的 JDBC 方式连接执行 SQL,获取 Kylin 的执行结果

  • 使用 Kylin 的 JDBC 与 JDBC 操作 MySQL 一致

业务需求

通过 JDBC 的方式,查询按照日期、区域、产品维度统计订单总额/总数量结果

开发步骤

添加依赖

<dependency>  <groupId>org.apache.kylin</groupId>  <artifactId>kylin-jdbc</artifactId>  <version>3.1.1</version></dependency>
复制代码

实现规划

  • 创建 Connection 连接对象

  • 构建 SQL 语句

  • 创建 Statement 对象,并执行 executeQuery

  • 打印结果

编写代码

我这里用 Scala 实现了,Java 也差不多


package icu.wzk.kylin
import java.sql.DriverManager
object KylinJdbcTest {
def main(args: Array[String]): Unit = { // 创建连接对象 val connection = DriverManager.getConnection("jdbc:kylin://h122.wzk.icu:7070/wzk_test_kylin", "ADMIN", "KYLIN") // 创建Statement val statement = connection.createStatement(); // 构建SQL语句 var sql = """ |select | t1.dt, | t2.regionid, | t2.regionname, | t3.productid, | t3.productname, | sum(t1.price) as total_money, | sum(t1.amount) as total_amount |from | dw_sales1 t1 |inner join dim_region t2 |on t1.regionid = t2.regionid |inner join dim_product t3 |on t1.productid = t3.productid |group by | t1.dt, | t2.regionid, | t2.regionname, | t3.productid, | t3.productname |order by | t1.dt, | t2.regionname, | t3.productname |""".stripMargin val resultSet = statement.executeQuery(sql) println("dt region product_name total_money total_amount") while (resultSet.next()) { // 获取时间 val dt = resultSet.getString("dt") // 获取区域名称 val regionName = resultSet.getString("regionname") // 获取产品名称 val productName = resultSet.getString("productname") // 获取累计金额 val totalMoney = resultSet.getDouble("total_money") // 获取累计数量 val totalAmount = resultSet.getDouble("total_amount") println(f"$dt $regionName $productName $totalMoney $totalAmount") } connection.close() }
}
复制代码

测试运行

我们运行代码,可以看到如下的运行结果:


错误速查

其他系列

🚀 AI 篇持续更新中(长期更新)

AI 炼丹日志-29 - 字节跳动 DeerFlow 深度研究框斜体样式架 私有部署 测试上手 架构研究,持续打造实用 AI 工具指南!AI 研究-127 Qwen2.5-Omni 深解:Thinker-Talker 双核、TMRoPE 与流式语音🔗 AI模块直达链接

💻 Java 篇持续更新中(长期更新)

Java-174 FastFDS 从单机到分布式文件存储:实战与架构取舍 MyBatis 已完结,Spring 已完结,Nginx 已完结,Tomcat 已完结,分布式服务已完结,Dubbo 已完结,MySQL 已完结,MongoDB 已完结,Neo4j 已完结,FastDFS 正在更新,深入浅出助你打牢基础!🔗 Java模块直达链接

📊 大数据板块已完成多项干货更新(300 篇):

包括 Hadoop、Hive、Kafka、Flink、ClickHouse、Elasticsearch 等二十余项核心组件,覆盖离线+实时数仓全栈!大数据-278 Spark MLib - 基础介绍 机器学习算法 梯度提升树 GBDT 案例 详解🔗 大数据模块直达链接

发布于: 16 分钟前阅读数: 6
用户头像

武子康

关注

永远好奇 无限进步 2019-04-14 加入

Hi, I'm Zikang,好奇心驱动的探索者 | INTJ / INFJ 我热爱探索一切值得深究的事物。对技术、成长、效率、认知、人生有着持续的好奇心和行动力。 坚信「飞轮效应」,相信每一次微小的积累,终将带来深远的改变。

评论

发布
暂无评论
大数据-163 Apache Kylin Segment 合并实战:手动/自动合并、保留策略与 JDBC 示例_scala_武子康_InfoQ写作社区