news 2026/6/10 9:44:14

Iceberg 与 Hive 用法区别

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Iceberg 与 Hive 用法区别

Iceberg 与 Hive 用法区别

  • 一、建表的区别
  • 二、分区的区别
    • 1. 分区字段的存储
    • 2. 分区与文件的关系
    • 3. 分区的类型
    • 4. 分区模式的变更
    • 5. 分区管理的区别
  • 三、Schema 变更的区别
  • 四、Spark3 写入的区别
    • 1. 事务性
    • 2. Insert into
    • 3. Insert overwrite
    • 4. 行级更新
    • 5. 写入优化
  • 五、Spark3 读取的区别

本文档介绍 Iceberg 和 Hive 在使用上的区别和注意事项,便于对 Hive 用户熟悉的用户快速上手 iceberg。以下
主要介绍 spark 使用 iceberg v1 表和 hive 表的区别。

一、建表的区别

hive 和 iceberg 使用 ddl 建表语法基本类似,iceberg 需要指定 using iceberg。

Iceberg 建表

createtableiceberg_zjyprc_hadoop.iceberg_dev.iceberg_table_test(idint,datastring,dateint)usingiceberg partitionedby(date);

Hive 建表:

createtablehive_zjyprc_hadoop.tmp.iceberg_table_test(idint,datastring,dateint)partitionedby(date);

二、分区的区别

Iceberg 的分区比 hive 的分区更加强大,但使用方式类似。区别主要在以下方面:

1. 分区字段的存储

Hive 表的分区字段是个虚拟字段,如设置 partitioned by (date) , date 字段不会实际在底层文件中存储,并且分区字段总是在字段顺序的最后面。
Iceberg 表的分区字段是实际字段,底层文件中也包含该字段,分区字段的位置不固定。

2. 分区与文件的关系

Hive 的分区和目录(一批文件)是一一映射的。hive 读取时必须 list 目录以获取分区下的所有文件。如果分区下的文件被手动删除,读取时不会出现任何异常。

Iceberg 的分区和文件是一一映射的,映射关系被记录在元数据文件中。在读取时通过扫描元数据文件获取分区对应的文件,由于元数据还记录了文件中字段的 min/max ,因此在读取时可以过滤一部分文件,达到文件裁剪的效果。由于文件记录在元数据中,如果该文件丢失或损坏在读取时会报异常。
元数据示例如下:

3. 分区的类型

Hive 只有一种分区类型。如通常使用 date 或 day、hour 等字段做时间分区。

Iceberg 支持多种分区类型。其中第一章节示例语法中的为 identity 分区,和 hive 的分区完全相同。此外还支持 bucket、truncate、day、hour 等分区类型。例如使用 bucket 分区可以将数据进行分桶存储以加快速度。

4. 分区模式的变更

Hive 表的分区模式在建表时确定,后续无法再增加、变更分区。当有新需求需要增加一个分区字段来加快查询时在 hive 上需要重写历史数据。

Iceberg 表的分区模式是可以变更的,修改分区模式不需要重写历史数据,该特性称为 Partition Evolution。
你可以使用如下语法增加和删除某个字段是否作为分区字段。注意该操作不是增加或删除一个分区的数据。

ALTERTABLEiceberg_zjyprc_hadoop.iceberg_dev.iceberg_table_testADDPARTITIONFIELDhour;ALTERTABLEiceberg_zjyprc_hadoop.iceberg_dev.iceberg_table_testDROPPARTITIONFIELDdate;

分区模式变更的原理是在元数据文件中维护了分区的不同模式,当分区模式发生变更后,新数据会以新的目录结构写入并被记录在元数据文件中,历史数据对应关系保持不变。

5. 分区管理的区别

  • 查看分区列表
    Hive 中可以使用 show partitions xxx 来查看分区,iceberg 中可以使用 如下语法来实现同样的功能。
select*fromiceberg_zjyprc_hadoop.iceberg_dev.iceberg_table_test.partitionslimit10
  • 删除分区数据
    Hive 中可以使用 alter table xxx drop partition(date=20230201) 来删除一个分区的数据。
    iceberg 中可以使用 delete from 指定删除某个符合条件的数据。当 where 条件匹配到某些分区时,只会修改元数据信息将匹配的文件删除,因此速度非常快。
deletefromxxxwheredate=20230201

三、Schema 变更的区别

Hive 和 Iceberg 都可以增加和删除字段,并调整字段顺序。主要区别有以下两个:

  1. Hive 不支持 rename 字段名, iceberg 支持 rename 字段名,并且重命名后不影响读取历史数据。
ALTERTABLEiceberg_zjyprc_hadoop.iceberg_dev.iceberg_table_testRENAMECOLUMNdateTOdt;ALTERTABLEiceberg_zjyprc_hadoop.iceberg_dev.iceberg_table_testADDCOLUMNhourint;


2. Iceberg 字段类型变更受限制。
目前只允许以下变更:

  • int to bigint
  • float to double
  • decimal(P,S) to decimal(P2,S) when P2 > P (scale cannot change)

四、Spark3 写入的区别

1. 事务性

当前的 Hive 版本写入不支持事务性,因此如果使用 overwrite 覆盖一个分区,则可能导致下游消费该分区的任务失败(报错 FileNotFound) 。
当使用 Spark 写入 Iceberg 时,每次写入都会生成一个新的快照,通过多快照的方式进行读写分离。

可以在引擎的 driver 日志中查找如下日志了解本次查询基于哪个快照执行的。

Scanningtableiceberg_zjyprc_hadoop.db_name.table_namesnapshot8893192237667870777created at2023-03-0902:10:04.718withfiltertrue

也可以在日志(spark driver 日志,flink commit 节点日志)中查询本次写入的事务对应的快照是哪个。

2023-03-0911:11:27.917INFO org.apache.iceberg.BaseMetastoreTableOperations Successfullycommittedtotableiceberg_zjyprc_hadoop.db.table_namein2541ms2023-03-0911:11:27.917INFO org.apache.iceberg.SnapshotProducer-Committedsnapshot1523286428440820440(MergeAppend)

由于 iceberg 多快照机制,一个分区目录下可能存在多个快照的文件,因此当使用 iceberg 时不要直接读取目录,而应该通过表的方式(dataframe、sql 等通过 catalog.db.table 三级结构)进行访问。

2. Insert into

  • 写 Hive 默认为静态分区,必须指定分区写入:
insertintohive_zjyprc_hadoop.tmp.iceberg_table_testpartition(date=20221210)values(1,'a'),(2,'b')

如果想实现动态分区写入,则需要配置参数

sethive.exec.dynamic.partition.mode=nonstrict;insertintohive_zjyprc_hadoop.tmp.iceberg_table_testvalues(1,'a',20221210),(2,'b',20221211)
  • 写 Iceberg 默认为动态分区,数据会写到对应的分区中:
insertintoiceberg_zjyprc_hadoop.iceberg_dev.iceberg_table_testvalues(1,'a',20230101,1),(2,'b',20230102,2)

同时也支持静态分区的写入方式:

insertintoiceberg_zjyprc_hadoop.iceberg_dev.iceberg_table_testpartition(date=20230103,hour=1)values(1,'a'),(2,'b')

3. Insert overwrite

  • Spark 覆盖写入Hive 默认为 static overwrite,必须指定分区:
insertoverwrite hive_zjyprc_hadoop.tmp.iceberg_table_testpartition(date=20220101)select1asid,'a'asdata
  • Spark 覆盖写入Iceberg 默认为 dynamic overwrite,覆盖的分区将会在运行阶段计算得到:
    – 覆盖 date=20230101/hour=1 和 date=20230101/hour=2 分区,
    – 但不会覆盖 date=20230101/hour=3 的分区
insertoverwrite iceberg_zjyprc_hadoop.iceberg_dev.iceberg_table_testvalues(1,'a',20230101,1),(2,'b',20230101,2)

下面两个写法和上述写法结果相同:
– All DP columns

insertoverwrite iceberg_zjyprc_hadoop.iceberg_dev.iceberg_table_testpartition(date,hour)values(1,'c',20230101,1),(2,'d',20230101,2)-- Mixed SP (static partition) & DP (dynamic partition) columnsinsertoverwrite iceberg_zjyprc_hadoop.iceberg_dev.iceberg_table_testpartition(date=20230101,hour)values(1,'b',1),(2,'c',2)-- All SP columnsinsertoverwrite iceberg_zjyprc_hadoop.iceberg_dev.iceberg_table_testpartition(date=20230101)values(1,'c',1),(2,'d',2)
  • 上面 dynamic overwrite 的行为,如果有两级分区,当指定一级分区覆盖时,被覆盖的二级分区取决于运行阶段查询出的数据,因此有可能有部分二级分区不会被删除。
  • Dynamic overwrite 是按照当前的分区模式进行判断的。比如历史分区模式是一级分区,当前分区模式是二级分区,那么 overwrite 时是按照二级分区的模式进行覆盖写,一级分区的历史数据不会被删除。

使用 static overwrite 和 写入 hive 默认行为表现一致。
可以通过配置 --conf set spark.sql.sources.partitionOverwriteMode=static 来设置为 static overwrite。

– 覆盖 date=20230101 下所有的分区的数据
– 如果没有指定 partition,那么所有的分区都会被覆盖删除

insertoverwrite iceberg_zjyprc_hadoop.iceberg_dev.iceberg_table_testpartition(date=20230101)values(1,'c',1),(2,'d',2)

4. 行级更新

当前的 hive 版本不支持行级更新,即不支持修改表中的某一行,只能使用 overwrite 覆盖整个分区。
Iceberg 支持使用 delete from、update、merge into 进行更新操作。参考:行级更新

5. 写入优化

Iceberg 会更多的优化,以进行降低存储和计算成本。

  • 建表策略
    Iceberg 针对不同场景的表提供了三种建表策略,以应对存储节约优先和查询性能优先,参考:建表策略
  • 排序写入
    由于 iceberg 存在 min\max 的索引信息,将常用的查询字段在写入时进行排序,可以获得更好的压缩效果和查询提速。参考:z-order 和 cluster by。
  • 小文件自动合并
    写入 iceberg 后台会自动完成小文件合并,减少存储并提高查询性能。参考:Binpack Compaction(文件合并)

五、Spark3 读取的区别

  • 在使用 Spark 查询时用法上基本相同。
    由于 Iceberg 是文件级别的过滤,当使用某个字段进行过滤时,即使该字段没有设置为分区,在查询时也会根据该字段的 min/max 进行过滤,配合 z-order 或 cluster by 等可以获得更好的过滤效果。
  • 读取 iceberg 要以表的方式访问,不要直接读取目录文件。
    由于 iceberg 读写都是基于元数据文件,因此需要通过表的方式来读,而不应该绕过元数据层直接读取数据文件,否则会出现数据重复的问题。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 1:06:44

传统vsAI:LDO设计效率提升10倍的秘密

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 使用快马平台对比传统和AI辅助的LDO设计流程。针对5V转1.8V/2A的LDO需求:1. 传统方法需要手动完成的步骤清单 2. AI自动完成的步骤清单 3. 两种方法的时间成本对比 4. 关…

作者头像 李华
网站建设 2026/6/10 16:27:55

AI如何帮你解决Cursor编程中的常见问题

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 创建一个AI辅助的代码编辑器,支持自动补全Cursor操作相关的代码片段。功能包括:1. 根据上下文智能提示Cursor操作(如移动、选择、删除等&#xf…

作者头像 李华
网站建设 2026/6/10 16:23:00

ET框架与AI结合:新一代游戏开发利器

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 创建一个基于ET框架的AI辅助游戏开发工具,主要功能包括:1. 使用Kimi-K2模型自动生成游戏NPC行为树;2. 通过DeepSeek模型分析游戏场景需求自动生成…

作者头像 李华
网站建设 2026/6/10 16:29:53

如何用AI自动生成Word搜索工具?GetWordSearch.exe开发指南

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 开发一个Windows桌面应用程序GetWordSearch.exe,功能包括:1) 读取文本文件内容 2) 实现关键词搜索功能 3) 高亮显示匹配结果 4) 支持正则表达式搜索 5) 提供…

作者头像 李华
网站建设 2026/6/10 17:10:04

电商系统实战:解决订单服务Bean初始化失败的完整案例

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 开发一个电商订单服务异常诊断模块,针对failed to instantiate错误:1. 模拟订单服务依赖注入场景 2. 包含典型错误案例(构造器参数缺失、接口多实现等) 3. 提…

作者头像 李华
网站建设 2026/6/10 12:02:59

JookDB在电商平台中的实战应用案例

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 开发一个电商平台演示系统,展示JookDB在以下场景的应用:1. 实时订单处理系统 2. 用户行为分析看板 3. 个性化推荐引擎。要求:使用JookDB作为主数…

作者头像 李华