- 数据湖
- 湖仓一体
- 大数据
【免费下载链接】iceberg
Apache Iceberg
本文基于 Iceberg 官方文档 site/docs/hive-quickstart.md 展开,完整复现“从零开始”的 Iceberg + Hive 环境搭建流程:用 Docker 一键启动 HiveServer2,通过 Beeline 执行 SQL 创建 Iceberg 表、写入数据并查询,同时结合 Iceberg 仓库中 mr、hive-metastore 两个模块的源码,解释STORED BY ICEBERG背后 Hive 存储处理器(StorageHandler)的组件链、谓词下推与表定位机制,帮助你既会用、又知其所以然。
一、准备环境:Docker + Hive 4
1. 选择 Hive 版本
最快的启动方式是使用 Apache Hive 官方 Docker 镜像,它提供类 SQL 接口,可以直接在笔记本上创建和查询 Iceberg 表。前提是你已安装 Docker Desktop。可用的 Hive 版本以镜像仓库 Tags 页为准。官方快速上手推荐:
export HIVE_VERSION=4.0.02. 启动 HiveServer2 容器
使用docker run启动容器,注意对搭载 M 系列芯片的 Mac 需要加上--platform linux/amd64参数:
docker run -d --platform linux/amd64 -p 10000:10000 -p 10002:10002 --env SERVICE_NAME=hiveserver2 --name hive4 apache/hive:${HIVE_VERSION}这条命令的关键点:
| 参数 | 作用 |
|---|---|
-p 10000:10000 | 暴露 HiveServer2 的 JDBC 端口,供 Beeline 连接 |
-p 10002:10002 | 暴露 Hive Web UI / 调试端口 |
--env SERVICE_NAME=hiveserver2 | 指定容器内启动的服务为 HiveServer2 |
--name hive4 | 容器命名,后续docker exec时引用 |
该镜像默认让 Hive Metastore 使用内嵌的 Derby 数据库。这里有一个重要的架构事实:Hive Metastore 充当 Iceberg 的 catalog(目录),负责定位 Iceberg 元数据文件,而这些文件本身可以存放在任何文件系统上。也就是说,HMS 里保存的是表的指针与 Hive 侧 schema 映射,真正的数据与 Iceberg 元数据在表的 location 下。
3. 用 Beeline 连接 HiveServer2
给容器中的 HS2 一点启动时间,然后执行:
docker exec -it hive4 beeline -u 'jdbc:hive2://localhost:10000/'看到如下提示符即表示连接成功:
0: jdbc:hive2://localhost:10000>接下来就可以运行 SQL 创建和查询 Iceberg 表了。先验证环境:
show databases;二、创建第一张 Iceberg 表
1. CREATE TABLE 配合 STORED BY ICEBERG
以官方示例中的nyc.taxis为例(nyc是数据库名,taxis是表名):
CREATE DATABASE nyc;CREATE TABLE nyc.taxis ( trip_id bigint, trip_distance float, fare_amount double, store_and_fwd_flag string ) PARTITIONED BY (vendor_id bigint) STORED BY ICEBERG;PARTITIONED BY (vendor_id bigint)并不会在 HMS 中创建 Hive 原生分区,而是被转换为 Iceberg 的identity 分区——分区值直接作为 Iceberg 分区字段记录在元数据中,DESCRIBE表时会看到对应的# Partition Transform Information信息(vendor_id对应IDENTITY转换类型)。
Iceberg catalog 支持完整的 SQL DDL 命令集,包括:
CREATE TABLECREATE TABLE AS SELECTCREATE TABLE LIKE TABLEALTER TABLEDROP TABLE
在 Hive 4 中还可以使用 Iceberg 原生分区语法直接指定转换函数,例如PARTITIONED BY SPEC (month(ts), bucket(2, i))。支持的转换与 Spark 一致:years(ts)、months(ts)、days(ts)/date(ts)、hours(ts)/date_hour(ts)、bucket(N, col)、truncate(L, col)。这些细节见 Hive 文档。
2. 写入数据
表创建后即可直接插入记录(注意列顺序包含分区列vendor_id):
INSERT INTO nyc.taxis VALUES (1000371, 1.8, 15.32, 'N', 1), (1000372, 2.5, 22.15, 'N', 2), (1000373, 0.9, 9.01, 'N', 2), (1000374, 8.4, 42.13, 'Y', 1);3. 读取数据
查询时直接使用 Iceberg 表名即可:
SELECT * FROM nyc.taxis;由于 Iceberg 的元数据中记录了每个数据文件/清单文件(manifest)的分区统计信息,Hive 读取 Iceberg 表时享有相对原生 Hive 表的明显收益:不需要列举文件系统目录、不需要从 Metastore 拉取分区列表、支持更细粒度的分区过滤,且可处理比原生 Hive 表更多的分区数量。
三、源码视角:STORED BY ICEBERG是如何工作的
1. HiveIcebergStorageHandler 组件链
STORED BY ICEBERG(Hive 4.0.0-alpha-1 起)是STORED BY 'org.apache.iceberg.mr.hive.HiveIcebergStorageHandler'的简写。核心实现位于 HiveIcebergStorageHandler,它同时实现了HiveStorageHandler与HiveStoragePredicateHandler两个接口,并向 Hive 注册四个核心组件:
| 组件 | 返回类型 | 职责 |
|---|---|---|
getInputFormatClass() | HiveIcebergInputFormat | 读取入口,基于 IcebergTableScan生成分片 |
getOutputFormatClass() | HiveIcebergOutputFormat | 写入口,配合HiveIcebergOutputCommitter提交快照 |
getSerDeClass() | HiveIcebergSerDe | 行列(反)序列化 |
getMetaHook() | HiveIcebergMetaHook | 在 DDL(建表、改 schema 等)时钩住 HMS 操作,同步 Iceberg 元数据 |
2. 谓词下推与表序列化
在 HiveIcebergStorageHandler 中可以看到两个值得关注的实现细节:
- 谓词下推:
decomposePredicate方法把 Hive 提取的 WHERE 过滤表达式同时标记为pushedPredicate和residualPredicate,即该过滤条件既下推到 Iceberg 的TableScan层做清单级裁剪,也由 Parquet/ORC Reader 在行组/行级别再次应用。 - 表对象传递:
overlayTableProperties方法通过Catalogs.loadTable加载 Iceberg 表,将表对象(含 schema、location、FileIO、加密信息等)序列化为 Base64 放入作业配置(SERIALIZED_TABLE_PREFIX + tableName),再由table(Configuration, name)静态方法在反序列化端还原——这保证了 Mapper/Reducer 端无需再访问 catalog 就能定位表;同时支持checkAndSkipIoConfigSerialization跳过 FileIO 中 Hadoop 配置的序列化以减小配置体积。
3. 表如何被定位:全局 catalog 与 iceberg.catalog 属性
Iceberg 通过 Catalogs 类解析表归属。Hive 侧只有一个由 Hadoop 配置定义的全局 catalog,而 Iceberg 表可能来自 Hive、Hadoop、Glue 等任意 catalog 甚至纯路径表,因此表在 HMS 中的iceberg.catalog属性决定三种加载方式:
- 未设置
iceberg.catalog:使用与当前 Hive 环境 Metastore 对应的HiveCatalog(默认路径); - 设置为已注册的 catalog 名:使用该自定义 catalog 加载;
- 设置为
location_based_table:直接用表根 location 加载,对应源码常量Catalogs.ICEBERG_HADOOP_TABLE_NAME = "location_based_table",内部走HadoopTables(conf).load(location)。
自定义 catalog 通过 Hadoop 配置全局注册,例如:
SET iceberg.catalog.another_hive.type=hive; SET iceberg.catalog.another_hive.uri=thrift://example.com:9083; SET iceberg.catalog.another_hive.warehouse=hdfs://example.com:8020/warehouse;| 配置键 | 说明 |
|---|---|
iceberg.catalog.<catalog_name>.type | catalog 类型:hive、hadoop,留空则用自定义 catalog |
iceberg.catalog.<catalog_name>.catalog-impl | 自定义 catalog 实现类,type 为空时必填 |
iceberg.catalog.<catalog_name>.<key> | 传给该 catalog 的任意配置键值对 |
这一机制还支持“overlay”场景:用CREATE EXTERNAL TABLE ... TBLPROPERTIES ('iceberg.catalog'='hadoop_cat')在 HMS 中为其他 catalog 中的 Iceberg 表建一张影子表,使不同 catalog 的表能在同一 Hive 环境中 join。
4. engine.hive.enabled:全局开关与按表开关
当 Iceberg storage handler 不在 Hive classpath 上时,Hive 无法为 Iceberg 表维护storage_handler元数据。为避免“看起来损坏”的表,Iceberg 只有在确认 Hive 支持被启用时才会把 storage handler 写入表,并在开关状态变化时同步增删。开关的判断逻辑在 HiveTableOperations 中清晰可见,优先级为:
- 表属性
engine.hive.enabled(表级,覆盖全局配置); - Hadoop 配置
iceberg.engine.hive.enabled(全局,如hive-site.xml); - 默认值。
因此两种启用方式:
- 全局:在 Hadoop 配置中设置
iceberg.engine.hive.enabled=true; - 按表:建表时加入表属性
engine.hive.enabled=true,例如通过 Java API:
Catalog catalog = ...; Map<String, String> tableProperties = Maps.newHashMap(); tableProperties.put(TableProperties.ENGINE_HIVE_ENABLED, "true"); // engine.hive.enabled=true catalog.createTable(tableId, schema, spec, tableProperties);此外源码 HiveVersion 枚举(HIVE_4/HIVE_3/HIVE_2/HIVE_1_2)表明 runtime 会在运行时探测 Hive 主版本,据此裁剪能力——这与下文的功能矩阵一一对应。
四、如果你已有 Hive 环境:如何启用 Iceberg 支持
1. Hive 4.0.0
如果你已有Hive 4.0.0 或更高版本环境,它自带hive-iceberg并内置 Iceberg(Hive 4.0.0 包含 Iceberg 1.4.3),无需额外下载或添加 jar。
2. Hive 2.3.x / Hive 3.1.x
旧版本需要手动加载 runtime jar 并显式启用支持:
add jar /path/to/iceberg-hive-runtime.jar;然后按上文“engine.hive.enabled”一节全局或按表启用。另外两点注意:
- 从 Iceberg 0.11.0 起,Hive 使用 Tez 引擎时必须关闭向量化:
hive.vectorized.execution.enabled=false; - 引擎限制:Hive 2.x/3.1.x 上 DML 仅支持 MapReduce 执行引擎;Hive 4 上 DML 仅支持 Tez 执行引擎。
五、能力边界与进阶方向
不同 Hive 版本对 Iceberg 表的功能支持差异较大(摘自 Hive 文档):
| 功能 | Hive 2 / 3 | Hive 4 |
|---|---|---|
| CREATE TABLE / CTAS / CTLT / DROP TABLE | 支持 | 支持 |
| INSERT INTO / INSERT OVERWRITE | 支持 | 支持 |
| DELETE FROM / UPDATE / MERGE INTO | 不支持 | 支持(Copy-on-Write) |
| Branches and tags | 不支持 | 支持 |
Hive 4 还额外支持:任意分区转换(transform)建表、schema 与分区演进保持双向同步、TRUNCATE/DROP PARTITION、非 ACID 的 Avro/Parquet/ORC 表一键迁移、元数据表查询(db.table.files、snapshots、partitions等)、时间旅行查询(FOR SYSTEM_TIME AS OF/FOR SYSTEM_VERSION AS OF)、分支读写(db.table.branch_<branch_name>)、ALTER TABLE ... EXECUTE expire_snapshots/ROLLBACK、OPTIMIZE TABLE ... REWRITE DATA全表压缩、表重命名、删除孤儿文件等。
当你完成本快速上手的建表、写入、查询闭环后,建议继续深入 Hive 与 Iceberg 完整文档,重点阅读其中的 DDL/DML 命令、类型兼容性映射表(Hivetimestamp对应 Icebergtimestamp without timezone、timestamplocaltz对应timestamp with timezone(仅 Hive 3)等)以及 catalog 管理章节,把本文演示的 Docker 环境平滑迁移到生产级集群。
- 数据湖
- 湖仓一体
- 大数据
【免费下载链接】iceberg
Apache Iceberg
相关推荐
Apache Hive 集成 Apache Iceberg 快速上手:Docker 环境下的建表、写入与查询实战指南
Apache Hive 集成 Apache Iceberg 快速上手:Docker 环境下的建表、写入与查询实战指南 Apache Iceberg 是面向大规模
数据湖大数据数据存储Apache Iceberg + Flink 快速上手实战:基于 Docker Compose 的 REST Catalog 环境搭建与 SQL 读写全流程
Apache Iceberg + Flink 快速上手实战:基于 Docker Compose 的 REST Catalog 环境搭建与 SQL 读写全流程 A
数据湖大数据数据存储Apache Iceberg 与 Spark 3 快速入门:从环境搭建到表读写与类型兼容
Apache Iceberg 与 Spark 3 快速入门:从环境搭建到表读写与类型兼容 Apache Iceberg 是面向大规模分析型数据湖的开放表格式,而
数据湖湖仓一体大数据
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考