避坑指南:Spark操作Iceberg分区表时那些意想不到的‘坑’(附正确姿势)

Apache Iceberg:现代数据湖的表操作系统与生产实践指南 数据湖表管理正从‘手动文件操作’迈向‘声明式元数据治理’。Apache Iceberg 作为开源数据表格式,以快照(Snapshot)、清单(Manifest)和元数据(Metadata)三层架构,实现跨引擎ACID事务、Time Travel、隐藏分区与确定性Schema演进。其核心价值在于解耦计算与存储,兼容Spark/Flink/Trino等引擎,不依赖特定云厂商,支撑PB级实时数仓与高并发写入场景。本文聚焦Iceberg在金融风控、电商实时分析等生产环境中的落地路径,涵盖Glue Catalog集成 阅读详情

Spark与Iceberg分区表实战:那些你必须绕开的“深坑”与最佳实践

如果你正在数据湖架构中尝试将Spark与Iceberg结合,尤其是处理分区表时,可能会遇到一些令人困惑甚至头疼的问题。表面上看,Iceberg的分区管理似乎比传统的Hive分区更灵活、更强大,但当你真正上手,尤其是在多引擎混用、版本升级或执行特定操作时,一些隐藏的“坑”就会浮现出来。这篇文章不是一篇泛泛而谈的入门教程,而是聚焦于中高级开发者在实际生产环境中,使用Spark操作Iceberg分区表时最容易踩中的几个关键陷阱。我会结合具体的场景、版本差异和实战代码,为你揭示问题根源,并提供经过验证的解决方案和最佳实践。

1. 理解Iceberg分区的核心机制:从Hive思维中跳出来

很多开发者是从Hive过渡到Iceberg的,这很容易带来一种思维惯性:认为分区就是目录,分区列就是表结构的一部分。Iceberg的分区设计理念与此有根本不同,这也是很多问题的源头。

Iceberg引入了隐藏分区和分区转换的概念。在Hive中,分区列是表结构的一部分,数据按分区列的物理目录存储。而在Iceberg中,分区是一种逻辑概念,它基于表中已有的列,通过一个转换函数(如days(ts)、bucket(16, id))计算得出。这个分区信息并不作为物理目录结构直接暴露,而是记录在元数据中。查询时,Iceberg会自动应用分区过滤,你甚至不需要在SQL中指定分区键。

这种设计带来了巨大的灵活性:你可以随时修改分区策略,而无需重写历史数据。但这也意味着,如果你用Hive的思维去创建或管理Iceberg分区表,很容易出问题。

关键区别:Hive分区是物理目录,分区列是表结构的一部分;Iceberg分区是逻辑定义,基于现有列的转换,信息存储在元数据里。

一个典型的误区是试图用Hive SQL的PARTITIONED BY子句来创建Iceberg的隐藏分区。例如,你有一个时间戳字段event_time,想按天分区。在Hive中你会直接PARTITIONED BY (event_date string)并手动或通过ETL填充这个列。在Iceberg中,正确的做法是使用分区转换函数,如PARTITIONED BY (days(event_time))。但这里就引出了我们的第一个大坑。

2. 深坑一:Hive语法创建分区表的致命局限

根据多个社区文档和实践反馈(包括输入资料中明确指出的),一个非常普遍且容易忽略的问题是:直接使用Hive的SQL语法(通过Hive引擎或Spark的Hive方言)创建的Iceberg分区表,无法使用Iceberg的分区转换功能。

问题场景: 假设你在Hive CLI或Spark SQL中(使用Hive Catalog)执行了如下建表语句:

CREATE TABLE my_iceberg_table (
    id BIGINT,
    data STRING,
    event_time TIMESTAMP
)
PARTITIONED BY (event_date STRING)
STORED BY 'org.apache.iceberg.mr.hive.HiveIcebergStorageHandler';

或者,在Spark SQL中(未正确配置Iceberg扩展)使用了类似语法。这张表确实是Iceberg格式,但它的分区方式被限制为Hive的模式。分区列event_date必须作为表的一个实际列存在,并且数据会按照event_date=2023-01-01/这样的目录结构存储。

致命后果:

  1. 无法使用分区转换:你不能再为这个表添加像days(event_time)、hour(event_time)或bucket(16, id)这样的隐藏分区。尝试使用ALTER TABLE ... ADD PARTITION FIELD会失败或无效。
  2. 分区演化受阻:Iceberg最强大的特性之一——在不重写数据的情况下修改分区策略——在这张表上基本失效。你被锁死在了建表时定义的物理分区列上。
  3. 管理混乱:你需要像管理Hive表一样,手动维护分区列的值和目录结构,失去了Iceberg自动管理分区的优势。

根本原因: 当通过Hive语法创建时,分区的信息被以Hive兼容的方式写入HMS(Hive Metastore),而Iceberg的隐藏分区和转换函数信息需要写入Iceberg自己的元数据文件(metadata.json)。Hive的创建路径没有触发Iceberg分区转换逻辑的初始化。

正确姿势: 务必使用Spark(3.x及以上)或Flink的引擎,并启用Iceberg的SQL扩展来创建支持分区转换的表。

Spark SQL示例(启用扩展后):

-- 确保在spark-defaults.conf中配置了扩展
-- spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions

CREATE TABLE my_catalog.db.my_iceberg_table (
    id BIGINT,
    data STRING,
    event_time TIMESTAMP
)
USING iceberg
PARTITIONED BY (days(event_time), bucket(16, id)); -- 这里使用了转换函数!

-- 插入数据时,无需指定分区值,Iceberg会自动计算
INSERT INTO my_catalog.db.my_iceberg_table VALUES
(1, 'test', '2023-10-27 10:30:00'),
(2, 'test2', '2023-10-27 15:45:00');

版本注意:确保你的Spark和Iceberg版本兼容。例如,Spark 3.3.x对应Iceberg 1.1.x是经过良好测试的组合。使用不匹配的版本可能导致某些扩展功能不可用。

检查表分区:创建后,你可以通过查询Iceberg的元数据表来验证分区规范:

SELECT * FROM my_catalog.db.my_iceberg_table.partition_specs;

你应该能看到类似 [1000] days(event_time), [1001] bucket(16, id) 的分区字段定义,而不是简单的列名。

3. 深坑二:动态分区覆盖(Overwrite)的诡异行为

动态分区覆盖(INSERT OVERWRITE 或 DataFrame的overwritePartitions())是一个常用操作,旨在只重写那些有数据落入的分区,而不是全表覆盖。在Hive中,这个行为相对直观。但在Iceberg中,尤其是在分区策略演化后,它的行为可能和你的预期大相径庭。

问题场景: 假设你有一张按day分区的表,最初数据分布在2023-10-26, 2023-10-27两个分区。你执行了一个动态覆盖写入,新数据只涉及2023-10-27分区。在Hive中,只有2023-10-27分区的数据会被替换。在Iceberg中,这通常是正确的。但是,如果你后来修改了表的分区策略,比如从按day分区改为按hour分区,问题就来了。

陷阱: Iceberg的分区覆盖逻辑与当前表最新的分区规范绑定。这意味着,即使你的历史数据是按day分区的,当你执行动态覆盖时,Iceberg会基于最新的分区规范(按hour) 来决定哪些分区被覆盖。

示例:

  1. 表logs初始分区规范:PARTITIONED BY (days(event_time))
  2. 插入数据到 2023-10-27 这一天。
  3. 修改分区:ALTER TABLE logs ADD PARTITION FIELD hours(event_time)
  4. 现在表有两个分区规范:spec-id=0 (按day) 和 spec-id=1 (按day+hour)。新数据使用spec-id=1。
  5. 你执行一个动态覆盖,新数据的时间戳是 2023-10-27 14:00:00。
    • 你的预期:覆盖 2023-10-27 这个天的分区(因为历史数据是按天存的)。
    • Iceberg的行为:它会覆盖 2023-10-27-14 这个小时分区(根据最新规范spec-id=1)。而2023-10-27这个天的分区(属于spec-id=0)不会被触动,里面的其他小时数据(如13点、15点)依然存在。

这会导致一个非常令人困惑的结果:查询按天过滤时,会发现2023-10-27的数据是新旧混合的——来自旧分区规范(天)中未被覆盖的部分,加上新分区规范(小时)中写入的部分。

解决方案与最佳实践:

  1. 理解分区演化的本质:Iceberg的分区演化是添加而非替换。旧数据保留在原分区布局中,新数据采用新布局。覆盖操作只针对写入时生效的分区布局。
  2. 谨慎使用动态覆盖:在分区策略发生过变化的表上使用overwritePartitions()要格外小心。最好先明确你的意图是覆盖旧布局的分区还是新布局的分区。
  3. 使用静态覆盖进行精确控制:如果需要对特定分区(无论属于哪个历史规范)进行覆盖,使用带有明确过滤条件的静态覆盖。
    // Spark DataFrame API 示例
    df.writeTo("my_catalog.db.logs")
      .overwrite($"event_time".between("2023-10-27", "2023-10-28")) // 覆盖特定时间范围
      // 或者针对旧分区规范的分区键进行覆盖(如果保留了分区列)
      // .overwrite($"day" === "2023-10-27")
    
  4. 查询时注意:查询引擎(如Spark)会自动处理跨多个分区规范的数据,但性能可能受影响。对于重要的历史报表,考虑将数据迁移到统一的新分区布局下。

4. 深坑三:分区列“删除”的误解与元数据残留

Iceberg允许你通过DROP PARTITION FIELD来移除一个分区字段。这听起来很美好,但它的实际行为需要深刻理解。

问题场景: 你有一张表,最初按category和days(event_time)分区。后来你觉得按category分区意义不大,决定删除它:

ALTER TABLE my_table DROP PARTITION FIELD category;

操作成功。你查看表结构,发现category列依然存在,只是不再是分区键。然后你插入新数据,发现新生成的数据文件不再按category进行分区存储。这似乎符合预期。

陷阱:

  1. 历史数据不受影响:DROP PARTITION FIELD是一个纯粹的元数据操作。它不会重写任何已有的数据文件。所有在删除操作之前写入的数据,仍然按照旧的分区规范(包含category)物理存储。元数据中会记录每条数据属于哪个分区规范(spec-id)。
  2. 动态覆盖行为再次变化:如上节所述,覆盖操作基于最新分区规范。删除category后,动态覆盖将不再考虑category维度。这可能导致数据覆盖范围比你预期的更广。
  3. 查询可能变慢或出错:虽然查询引擎能处理多分区规范,但一些优化(如分区剪裁)在涉及已删除的分区字段时可能效果不佳。如果查询条件中包含了已删除的分区字段,在读取旧数据时可能无法有效过滤。

正确理解与操作建议:

  • “删除”实为“停用”:更准确地说,DROP PARTITION FIELD是为未来的写入停用了该分区字段,并将其从当前活跃的分区规范中移除。历史分区布局被冻结。
  • 无法真正“清理”:没有一个命令能“清理”或“重组”历史数据使其符合新的分区布局。如果这确实是你的需求(比如释放category分区带来的小文件开销),你需要启动一个重写数据文件的任务,使用最新的分区规范。
    -- 使用Spark存储过程重写数据文件(需要Spark扩展)
    CALL my_catalog.system.rewrite_data_files('db.my_table');
    
    这个操作会重写数据文件,使其符合当前表最新的分区规范和排序顺序。这是一个重量级操作,类似于Hive的INSERT OVERWRITE TABLE ... SELECT * FROM ...,但由Iceberg以事务方式完成。
  • 规划先行:在设计表分区时,尽量考虑长远。频繁增加和删除分区字段会导致元数据复杂,查询性能下降,管理成本升高。一个稳定的分区策略比一个灵活但多变的分区策略更利于生产系统。

5. 实战配置与版本兼容性要点

避开上述逻辑上的“坑”之后,技术栈的正确配置是保证一切正常运行的基础。这里汇总几个关键配置点和版本陷阱。

Spark与Iceberg集成配置核心:

  1. Catalog配置:这是第一步,也是出错最多的一步。

    # 在 spark-defaults.conf 或 SparkSession Builder 中配置
    # 使用Hive Catalog (元数据存在HMS)
    spark.sql.catalog.my_hive_catalog = org.apache.iceberg.spark.SparkCatalog
    spark.sql.catalog.my_hive_catalog.type = hive
    spark.sql.catalog.my_hive_catalog.uri = thrift://hive-metastore-host:9083
    spark.sql.catalog.my_hive_catalog.warehouse = hdfs:///path/to/warehouse
    
    # 使用Hadoop Catalog (元数据存在文件系统)
    spark.sql.catalog.my_hadoop_catalog = org.apache.iceberg.spark.SparkCatalog
    spark.sql.catalog.my_hadoop_catalog.type = hadoop
    spark.sql.catalog.my_hadoop_catalog.warehouse = hdfs:///path/to/warehouse
    
    • 关键点:warehouse路径是Iceberg管理元数据和数据的根目录,不是Hive的warehouse。两者可以不同。
  2. 启用SQL扩展(必须):为了使用CREATE TABLE ... PARTITIONED BY (days(...))、ADD/DROP PARTITION FIELD等高级DDL,必须启用Spark扩展。

    spark.sql.extensions = org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions
    

    没有这个配置,上述很多分区操作将无法识别语法。

  3. 版本矩阵:严重建议查阅官方文档的版本兼容性矩阵。这里给出一个常见的稳定组合参考:

    Spark 版本推荐 Iceberg 版本重要特性支持
    3.3.x1.1.x完整DDL支持,存储过程,时间旅行
    3.2.x1.0.x - 1.1.x核心功能支持良好
    3.1.x0.12.x - 1.1.x基础支持,部分高级DDL可能受限

    使用不匹配的版本,可能会遇到类找不到、方法不存在或语法不支持的错误。

写入性能与小文件优化: Iceberg不会自动合并小文件,这是与Hive不同的另一个地方。频繁的流式写入或小批量写入会产生大量小文件,影响查询性能。

  • 调整写入目标文件大小:
    ALTER TABLE my_catalog.db.my_table SET TBLPROPERTIES ('write.target-file-size-bytes'='536870912'); -- 512MB
    
  • 定期压缩数据文件:这是生产环境必不可少的维护作业。可以使用Spark定期调度执行。
    import org.apache.iceberg.spark.actions.SparkActions
    
    val table = // ... 加载你的Table对象
    SparkActions.get(spark)
      .rewriteDataFiles(table)
      .filter(Expressions.greaterThan("event_time", "2023-10-01")) // 可选:只压缩特定分区
      .option("target-file-size-bytes", "536870912")
      .execute()
    
  • 快照过期与孤儿文件清理:同样需要定期维护。
    // 过期1天前的快照
    table.expireSnapshots()
      .expireOlderThan(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1))
      .commit()
    
    // 删除孤儿文件(未被任何快照引用的数据文件)
    SparkActions.get(spark)
      .deleteOrphanFiles(table)
      .olderThan(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(3))
      .execute()
    

6. 总结:从“踩坑”到“驾驭”

Spark与Iceberg的结合为数据湖带来了强大的事务能力、模式演化和隐藏分区等特性,但其分区管理机制与传统的Hive有显著差异。要平稳驾驭,关键在于转变思维:

  1. 摒弃Hive的物理分区思维,拥抱Iceberg的逻辑分区和分区转换。
  2. 创建表时,坚持使用Spark/Flink引擎并启用扩展,避免使用纯Hive语法,以确保获得完整的Iceberg分区功能。
  3. 深入理解分区演化、动态覆盖与历史数据的关系,意识到这些操作是基于多版本分区规范共存的上下文进行的。
  4. 将“删除分区字段”视为“停用”,并知晓其对历史数据和未来操作的影响。
  5. 建立例行维护流程,包括压缩小文件、清理快照和孤儿文件,以保持表的最佳性能。
  6. 严格遵循版本兼容性,并在测试环境中充分验证核心操作流程。

Iceberg的分区设计在提供巨大灵活性的同时,也将更多的责任交给了使用者。清晰的设计、谨慎的操作和持续的维护,是发挥其优势、避免其陷阱的不二法门。当你透彻理解这些机制后,Iceberg分区表将成为你构建高效、灵活数据湖的利器,而非烦恼的来源。

Spark与Iceberg集成:开源数据表格式实践 想象一下,2023年某电商平台的"双11"大促场景:数据团队凌晨3点接到紧急告警,昨天的销售报表数据异常,需要立即排查。分析师尝试回溯数据,却发现由于频繁的ETL操作,原始数据早已被覆盖;数据工程师试图调整分区策略优化查询性能,却发现传统表格式不支持无停机的分区变更;与此同时,实时计算团队需要基于相同的数据集构建流处理管道,却面临批流数据一致性的挑战。这并非虚构场景,而是数据湖发展过程中普遍面临的"冰火两重天"困境:一方面是数据价值挖掘的迫切需求(“火”),另一方面是数据管理技术的滞后(“冰”)。 阅读详情

相关推荐

数据湖(十三):Spark与Iceberg整合DDL操作

文章目录Spark与Iceberg整合DDL操作一、​​​​​​​CREATE TABLE 创建表二、​​​​​​​​​​​​​​CREATE TAEBL ... AS SELECT1、创建表hadoop_prod.default.mytbl,并插入数据2、使用“create table ... as select”语法创建表mytal2并查询 三、REPLACE TABLE ... AS SELECT1、创建表“hadoop_prod.default.mytbl3”,并插入数据、展示2、重建表“hado

Lansonli(蓝深李)的博客 1609

Spark + Iceberg实战:电商大促场景下的数据湖治理避坑指南

本文针对电商大促场景下的数据治理痛点,提供了基于Spark与Iceberg数据湖架构的实战避坑指南。文章详细阐述了如何利用Iceberg的时间旅行、Schema演进、事务支持等核心特性,结合Spark进行高性能配置与调优,以解决数据回溯、并发写入、小文件治理等典型挑战,构建稳定高效的数据平台。

1007

Spark集成Iceberg

Iceberg

weixin_41367158的博客 298

ALTER TABLE 分区操作-动态增加一级,多级分区,动态删除分区

1.8.5.6 ALTER TABLE 分区操作 alter 分区操作包括增加分区和删除分区操作,这种分区操作在Spark3.x之后被支持,spark2.4版本不支持,并且使用时,必须在spark配置中加入spark.sql.extensions属性,其值为:org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions,在添加...

weixin_48370579的博客 4252

【大数据入门核心技术-Iceberg】(五)Iceberg与Spark基本Shell操作

这将保留一些元数据文件(直到write.metadata.previous-versions-max),并在每个新创建的元数据文件之后删除旧的元数据文件。Spark中支持两种Catalog的设置:hive和hadoop,Hive Catalog就是Iceberg表存储使用Hive默认的数据路径,Hadoop Catalog需要指定Iceberg格式表存储路径。例如,如果按天划分分区,而改为按小时划分分区,那么覆盖将覆盖每小时划分的分区,而不再覆盖按天划分的分区。-- 在数组中的结构中添加一个字段。

628

安卓ai自动化脚本 Yyds.Auto实现 示例 纯ai图像识别自动点击脚本

纯ai识别实现自动化脚本

专注安卓前沿科技 4785

Iceberg 基本操作和快速入门二-Spark DDL操作

启动spark会话proddbsampleiddatastringUSINGiceberg;id bigint,proddbsamplepayload;proddbsampleid;');----语法---示例DROP TABLEproddbsample;DROP TABLEproddb;

u010479989的博客 1505

【C++PTA】6-1 Point类的运算 (10 分)

定义Point类,有坐标x,y两个私有成员变量;对Point类重载“+”(相加)、“-”(相减)和“==”(相等)运算符,实现对坐标的改变,要求用友元函数和成员函数两种方法实现。对Point类重载<<运算符,以使得代码 Point p; cout<<p<<endl;可以输出该点对象的坐标。 函数接口定义: 实现Point类。 裁判测试程序样例: /* 请在这里填写答案 */ int main(int argc, char const *argv[]) { P

libertye的博客 2369

【Iceberg分析】调研Iceberg中表的原地演变

iceberg的表的原地演变

有问题的请私信或关注v【技术印记】留言 1650

云安全技术——搭建VPN

VPN(Virtual Private Network)是一种可以在公共网络上建立安全连接的技术。VPN是实现保密通信的基本手段,在windows系统上,可以直接进行VPN服务的搭建。1.VPN的工作原理:通过使用加密协议和认证机制,将本地计算机和远程服务器之间的通信加密和保护。2.VPN的分类:根据不同的方式和用途,VPN可以分为不同类型,例如远程访问VPN、站点到站点VPN等。3.VPN的优势:VPN可以带来许多好处,如提高数据安全性、隐藏真实IP地址、突破地理限制等。4.

qq_53142796的博客 3万+

hcaptcha无感验证码逆向实战:从接口分析到环境补全

本文详细解析了hcaptcha无感验证码的逆向实战过程。通过分析核心接口与加密逻辑,重点介绍了采用环境补全策略来模拟真实浏览器环境,从而绕过验证码检测。文章提供了从接口抓包、剖析hsw.js加密核心到使用Node.js搭建模拟环境的完整步骤,为自动化操作提供了一种稳健的解决方案。

weixin_29324401的博客 1156

Apache Iceberg 分区表探索与实践

组件版本 组件 版本 Apache Iceberg 0.11 Apache Hive 2.1.0 Apache Spark 3.0 Apache Flink 1.11 文章目录简介测试分区表功能建表写入数据重写指定分区重写动态分区 简介 本篇介绍Apache Icerberg分区表自己的一些探索与实践,包括建表、数据写入、重写分区、删除分区、添加分区,数据链路操作设计如下图: 备注: 创建分区表、修改标属性:使用Hive 批量写入数据、重写分区:使用Spark 实时计算.

高矮 2760

CTP开发实战:如何高效处理预埋单与委托单的完整流程(附代码示例)

本文深入探讨了CTP开发中预埋单与委托单的完整处理流程,从订单生命周期理解、核心代码实现到异步事件处理与系统健壮性构建。通过详细的代码示例和状态机分析,为开发者提供了构建高可靠订单处理系统的实战指南,重点解决了状态同步、异常恢复等关键工程挑战。

weixin_29234239的博客 118

Apache Iceberg + Spark 快速上手指南:从 Docker Compose 到表读写与 Catalog 配置

Apache Iceberg™ 是面向大规模分析型数据湖的开源表格式,而 Apache Spark™ 是 Iceberg 最常用的计算引擎之一。本指南以仓库中的 [spark-quickstart.md](https://link.gitcode.com/i/3d5ab7c7388b1d9a97a16b32fe7c89fc) 为骨架,完整讲解如何用 Docker Compose 一键拉起带 Ice

gitblog_00478的博客 462

自动化测试工具playwright中文文档-------1.编写测试

Playwright 测试非常简单,它们执行操作,并断言状态是否符合预期。在执行任何操作之前,无需等待任何内容:Playwright 在执行每个操作之前会自动等待一系列可操作性检查通过。此外,在执行检查时也不需要处理竞态条件——Playwright 的断言设计方式能够描述最终需要满足的期望。就这样!这些设计选择允许 Playwright 用户完全忘记他们测试中的不稳定超时和竞态检查。您将学习如何编写第一个测试如何执行操作如何使用断言测试如何在隔离环境中运行如何使用测试钩子。

2301_76646967的博客 2511

Unity-TextMeshPro如何扩展材质实现字体Face+Outline流光效果

前言 TexeMeshPro 是Unity的一个Text文本插件,实现了比UGUI的Text,更好看的效果,跟高效的性能,所以深受大家的喜欢,但是再好的插件,也不是万能的,比如我们的策划有个新需求,要我们的VIP的名字比普通玩家有更好看的效果,例如:字体流光,外发光颜色扰动,字体贴图等等。那我们就需要去扩展TextMeshPRo的shader功能了。如下图所示 本文,我就带大家一起来扩展一下:如何扩展TextMeshProUGUI TextMesh原始面板 扩展功能后的面板 扩展TextMeshPro

TxNet 9690

Iceberg与SparkSQL整合DDL操作

使用SparkSql操作Iceberg表之前我们得先配置好catalog,配置方式参考[这篇博客]。

SunnyRivers 1974

Cartographer实现双雷达建图

TRAJECTORY_BUILDER_2D.num_accumulated_range_data = 2 --执行一次前端匹配需要的激光扫描分段数量。关于num_subdivisions_per_laser_scan。num_laser_scans =2,--订阅激光扫描话题数量。Frame改为 前雷达laser_1 后雷达laser_2。雷达的话题由scan改为,前scan_1 后scan_2。有些人说需要改成2,但我这里改成2反而不行,1才可以。

Studying…… 1261

Apache Iceberg实战教程:5分钟上手Spark集成与表创建

你还在为数据湖表的事务一致性、Schema演进和历史数据查询而烦恼吗?Apache Iceberg(冰山表)作为下一代数据湖解决方案,彻底解决了传统数据湖的痛点。本文将带你5分钟内完成Iceberg与Spark的集成配置、表创建和基础操作,让你快速掌握这一革命性的数据管理技术。 读完本文你将获得: - 从零开始的Spark-Iceberg环境配置指南 - 3种不同类型Catalog的实战配置 -...

gitblog_00347的博客 1285

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Hive分区表 vs 非分区表:SparkSQL数据写入的避坑指南(附真实案例)

本文通过一个真实案例,深入剖析了SparkSQL向Hive表执行INSERT OVERWRITE操作时,因并发写入导致数据重复的根本原因。核心在于非分区表因路径和元数据更新冲突而存在风险,而分区表通过路径隔离和元数据操作隔离有效规避了此问题。文章详细解释了SparkSQL的写入流程、元数据更新机制,并提供了配置动态分区覆盖模式(spark.sql.sources.partitionOverwriteMode=dynamic)的实战指南与代码示例,帮助开发者构建健壮的数据写入流程。

websocket5live的博客 192

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Apache Iceberg 与 Spark Structured Streaming 实战指南:流式读写、微批限流与表维护

本文基于 Apache Iceberg 官方文档中的 Structured Streaming 章节,系统讲解如何借助 Spark 的 DataSourceV2 API 让 Iceberg 表参与结构化流式计算:既可以从历史时间戳开始增量读取追加数据,也可以通过 `DataStreamWriter` 持续写入 Iceberg 表。读完本文,你将掌握流式读写的核心选项(`stream-from-ti

gitblog_00920的博客 205

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

数据湖之iceberg系列(四)iceberg-spark编程

1 创建maven项目 添加依赖 <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <scala.version>2.12.12</scala.version> <spark

HANG.NIAN 2784

Iceberg与hive的集成

2.上传jar包拷贝到Hive的auxlib目录下3.修改hive-site.xml使用TEZ引擎注意事项:(1)使用hive版本>=3.1.2,需要TEZ版本>=0.10.1(4)启动HMS服务。

2503_94597397的博客 319

Apache Iceberg 与 Spark 快速上手:Catalog 配置、建表读写与类型兼容性实战指南

Apache Iceberg 是一套面向大规模分析型数据湖的开放表格式,而 Spark 是目前支持 Iceberg 能力最完整的计算引擎之一。本文以仓库中的 [Spark 快速入门文档](https://link.gitcode.com/i/b75ee4b436e54f9b18b27c7e9676a1bb) 为骨架,结合 [Spark 配置](https://link.gitcode.com/i/

gitblog_00133的博客 87

Iceberg:基于Spark3.x的MERGE INTO语法实现数据的增量写入

/ 新旧数据记录,Merge阶段,会为每一个结果行添加一个新的列,其列名就这个常量。

Dreamming Time的博客 2933
上一篇: LaTeX表格进阶:实现底部注释自动对齐与页面宽度自适应
下一篇: 数字滤波器实战:从IIR到FIR,5种结构优缺点全解析(附MATLAB代码)
java5
博客等级 码龄22年 85粉丝 2103原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值