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

调研Iceberg中表的原地演变

文章目录

  • 调研Iceberg中表的原地演变
    • 原生非分区表
      • 文件关系图
      • 表的原地演变之表schema演变
        • 新增字段new_column
        • 文件关系变化图
        • 为新增字段写入数据
        • 文件关系变化图
        • 删除新增字段
        • 文件关系变化图
        • 新增字段new_column2
        • 文件关系变化图
        • 删除数据
        • 文件关系变化图
    • 原生分区表
      • Iceberg支持如下几种分区转换
      • 文件关系变化图
      • 表的原地演变之分区演变
        • 新增分区
        • 文件关系变化图
        • 删除分区
        • 删除数据
        • 文件关系变化图
    • 小结

以《基于spark3.4.2+iceberg1.6.1搭建本地阅读调试环境》为基础环境,调研原地演变特性

工程中iceberg_warehousespark.sql.catalog.local.warehouse 指定了 Iceberg 数据文件和元数据文件的存放路径。

原生非分区表

创建非分区原生表,并插入数据。

        // 1.创建库spark.sql("create database iceberg_db");// 2.新建表spark.sql("CREATE TABLE local.iceberg_db.table1 (id bigint, data string) USING iceberg ");// 3.第1次新增数据spark.sql("INSERT INTO local.iceberg_db.table1 VALUES (1, 'a'), (2, 'b'), (3, 'c')");// 4.第2次新增数据spark.sql("INSERT INTO local.iceberg_db.table1 VALUES (4, 'd'), (5, 'e'), (6, 'f')");// 5.第3次新增数据spark.sql("INSERT INTO local.iceberg_db.table1 VALUES (7, 'g'), (8, 'h'), (9, 'i')");

在这里插入图片描述

文件关系图

数据层
元数据层
catalog
data files
parquet格式
data files
parquet格式
data files
parquet格式
v1.metadata.json
v2.metadata.json
v3.metadata.json
v4.metadata.json
Manifest list
avro格式
Manifest list
avro格式
Manifest list
avro格式
Manifest file
avro格式
Manifest file
avro格式
Manifest file
avro格式
ceberg_db.table1

新建表时,会触发元数据的变化,此时是没有数据文件的,所以只有v1.metadata.json文件。

  • snap-开头的是清单列表文件(manifest list)
  • 紧接着snap之后的数字开头的是清单文件(manifest file)

表的原地演变之表schema演变

新增字段new_column
        // 6.新增字段new_columnspark.sql("ALTER TABLE local.iceberg_db.table1 " +"ADD COLUMNS ( new_column string comment 'new_column docs' )");
文件关系变化图
数据层
元数据层
catalog
data files
parquet格式
data files
parquet格式
data files
parquet格式
v1.metadata.json
v2.metadata.json
v3.metadata.json
v4.metadata.json
Manifest list
avro格式
Manifest list
avro格式
Manifest list
avro格式
Manifest file
avro格式
Manifest file
avro格式
Manifest file
avro格式
v5.metadata.json
ceberg_db.table1

v5.metadata.jsonschemas以数组的形式记录了不同的表schema。以schema-id区分。new_column字段上有对应的字段id3current-schema-id中是当前生效的schema-id

 "current-schema-id" : 1,
"schemas" : [ {"type" : "struct","schema-id" : 0,"fields" : [ {"id" : 1,"name" : "id","required" : false,"type" : "long"}, {"id" : 2,"name" : "data","required" : false,"type" : "string"} ]}, {"type" : "struct","schema-id" : 1,"fields" : [ {"id" : 1,"name" : "id","required" : false,"type" : "long"}, {"id" : 2,"name" : "data","required" : false,"type" : "string"}, {"id" : 3,"name" : "new_column","required" : false,"type" : "string","doc" : "new_column docs"} ]} ]
为新增字段写入数据
        // 7.为新增字段new_column增加数据spark.sql("INSERT INTO local.iceberg_db.table1 VALUES (10, 'j','new1'), (11, 'k','new2'), (12, 'l','new3')");Dataset<Row> result = spark.sql("select * from local.iceberg_db.table1");result.show();

查询结果

表的schema中新增字段在之前的记录以null填充展示。

+---+----+----------+
| id|data|new_column|
+---+----+----------+
|  7|   g|      null|
|  8|   h|      null|
|  9|   i|      null|
|  1|   a|      null|
|  2|   b|      null|
|  3|   c|      null|
| 10|   j|      new1|
| 11|   k|      new2|
| 12|   l|      new3|
|  4|   d|      null|
|  5|   e|      null|
|  6|   f|      null|
+---+----+----------+
文件关系变化图
数据层
元数据层
catalog
data files
parquet格式
data files
parquet格式
data files
parquet格式
data files
parquet格式
v1.metadata.json
v2.metadata.json
v3.metadata.json
v4.metadata.json
Manifest list
avro格式
Manifest list
avro格式
Manifest list
avro格式
Manifest file
avro格式
Manifest file
avro格式
Manifest file
avro格式
v5.metadata.json
v6.metadata.json
Manifest list
avro格式
Manifest file
avro格式
ceberg_db.table1
删除新增字段
        // 8.删除字段new_columnspark.sql("ALTER TABLE local.iceberg_db.table1 DROP COLUMNS new_column");Dataset<Row> result = spark.sql("select * from local.iceberg_db.table1");result.show();

查询结果

表schema的删除字段在,之前的记录全部除了删除字段,全部可以查询展示。

+---+----+
| id|data|
+---+----+
|  4|   d|
|  5|   e|
|  6|   f|
|  1|   a|
|  2|   b|
|  3|   c|
| 10|   j|
| 11|   k|
| 12|   l|
|  7|   g|
|  8|   h|
|  9|   i|
+---+----+
文件关系变化图
数据层
元数据层
catalog
data files
parquet格式
data files
parquet格式
data files
parquet格式
data files
parquet格式
v1.metadata.json
v2.metadata.json
v3.metadata.json
v4.metadata.json
v5.metadata.json
v6.metadata.json
v7.metadata.json
Manifest list
avro格式
Manifest list
avro格式
Manifest list
avro格式
Manifest list
avro格式
Manifest file
avro格式
Manifest file
avro格式
Manifest file
avro格式
Manifest file
avro格式
ceberg_db.table1

v7.metadata.jsoncurrent-schema-id中是当前生效的schema-id改为了0

新增字段new_column2
        // 9.删除字段new_columnspark.sql("ALTER TABLE local.iceberg_db.table1 " +"ADD COLUMNS ( new_column2 string comment 'new_column2 docs' )");
文件关系变化图
数据层
元数据层
catalog
data files
parquet格式
data files
parquet格式
data files
parquet格式
data files
parquet格式
v1.metadata.json
v2.metadata.json
v3.metadata.json
v4.metadata.json
v5.metadata.json
v6.metadata.json
v7.metadata.json
v8.metadata.json
Manifest list
avro格式
Manifest list
avro格式
Manifest list
avro格式
Manifest list
avro格式
Manifest file
avro格式
Manifest file
avro格式
Manifest file
avro格式
Manifest file
avro格式
ceberg_db.table1

v8.metadata.jsonschemas的变化,删除字段new_column的id3,不会再之后新增的new_column2不会再使用了。

"current-schema-id" : 2,
"schemas" : [ {"type" : "struct","schema-id" : 0,"fields" : [ {"id" : 1,"name" : "id","required" : false,"type" : "long"}, {"id" : 2,"name" : "data","required" : false,"type" : "string"} ]
}, {"type" : "struct","schema-id" : 1,"fields" : [ {"id" : 1,"name" : "id","required" : false,"type" : "long"}, {"id" : 2,"name" : "data","required" : false,"type" : "string"}, {"id" : 3,"name" : "new_column","required" : false,"type" : "string","doc" : "new_column docs"} ]
}, {"type" : "struct","schema-id" : 2,"fields" : [ {"id" : 1,"name" : "id","required" : false,"type" : "long"}, {"id" : 2,"name" : "data","required" : false,"type" : "string"}, {"id" : 4,"name" : "new_column2","required" : false,"type" : "string","doc" : "new_column2 docs"} ]
} ]
删除数据
        // 10.删除字段new_columnspark.sql("DELETE FROM local.iceberg_db.table1  where id in (2,5,10)");Dataset<Row> result = spark.sql("select * from local.iceberg_db.table1");result.show();
文件关系变化图
数据层
元数据层
catalog
data files
parquet格式
data files
parquet格式
data files
parquet格式
data files
parquet格式
data files
parquet格式
v1.metadata.json
v2.metadata.json
v3.metadata.json
v4.metadata.json
v5.metadata.json
v6.metadata.json
v7.metadata.json
v8.metadata.json
v9.metadata.json
Manifest list
avro格式
Manifest list
avro格式
Manifest list
avro格式
Manifest list
avro格式
Manifest list
avro格式
Manifest file
avro格式
Manifest file
avro格式
Manifest file
avro格式
Manifest file
avro格式
Manifest file
avro格式
Manifest file
avro格式
Manifest file
avro格式
Manifest file
avro格式
ceberg_db.table1

不同版本的metadata文件会使用不同的清单文件指向相同的数据文件,清单文件(manifest file)中的status字段取值说明,值1代表add,值2代表删除。

原生分区表

Iceberg支持如下几种分区转换

转换名称描述源字段类型结果类型
identityid值,默认没有转换函数。注意:如果用时间戳做为分区的话,每个时间戳是一个分区,随着数据的写入,元数据很快会崩溃AnySource type
bucket[N]哈希值],模Nint, long, decimal, date, time, timestamp, timestamptz, timestamp_ns, timestamptz_ns, string, uuid, fixed, binaryint
truncate[W]将字段按宽度截取int, long, decimal, string, binary与源字段类型一致,如果源字段是字符串则截取W长度,如果是int/long则相除W倍后取整
year将时间转换为年date, timestamp, timestamptz, timestamp_ns, timestamptz_nsint
month将时间转换为月date, timestamp, timestamptz, timestamp_ns, timestamptz_nsint
day将时间转换为日date, timestamp, timestamptz, timestamp_ns, timestamptz_nsint
hour将时间转换为小时timestamp, timestamptz, timestamp_ns, timestamptz_nsint
voidAlways produces nullAnySource type or int

创建分区原生表,使用分区转换进行隐藏分区,并插入数据。

        // 1.创建分区表,以month方法进行隐藏式分区spark.sql("CREATE TABLE local.iceberg_db.table2( id bigint, data string, ts timestamp) USING iceberg PARTITIONED BY (month(ts))");// 2.新增数据spark.sql("INSERT INTO local.iceberg_db.table2 VALUES (1, 'a', cast(1727601585 as timestamp)),(2, 'b', cast(1724923185 as timestamp)),(3, 'c', cast(1724919585 as timestamp))");

在这里插入图片描述

文件关系变化图

数据层
元数据层
catalog
ts_month=2024-08
ts_month=2024-09
data files
parquet格式
data files
parquet格式
v1.metadata.json
v2.metadata.json
Manifest list
avro格式
Manifest file
avro格式
ceberg_db.table2

Iceberg 通过获取列值并对其进行可选转换来生成分区值。建表时,ts字段类型是使用timestamp,默认使用带时区的timestamptz

v1.metadata.jsonpartition-specs以数组的形式记录了不同的表分区规则,以spec-id区分。default-spec-id中是当前生效的spec-id

  "default-spec-id" : 0,"partition-specs" : [ {"spec-id" : 0,"fields" : [ {"name" : "ts_month","transform" : "month","source-id" : 3,"field-id" : 1000} ]} ]

表的原地演变之分区演变

新增分区
        // 3.以day()方法新增分区spark.sql("ALTER TABLE local.iceberg_db.table2 ADD PARTITION FIELD day(ts)");// 4.新增数据spark.sql("INSERT INTO local.iceberg_db.table2 VALUES (4, 'd', cast(1727605185 as timestamp)),(5, 'e', cast(1725963585 as timestamp)),(6, 'f', cast(1726827585 as timestamp))");
文件关系变化图
数据层
元数据层
catalog
ts_month=2024-09
ts_month=2024-08
ts_day=2024-09-10
ts_day=2024-09-20
ts_day=2024-09-29
data files
parquet格式
data files
parquet格式
data files
parquet格式
data files
parquet格式
data files
parquet格式
v1.metadata.json
v2.metadata.json
v3.metadata.json
v4.metadata.json
Manifest list
avro格式
Manifest list
avro格式
Manifest file
avro格式
Manifest file
avro格式
ceberg_db.table2

v3.metadata.jsonpartition-specs的变化,default-spec-id采用了新的分区组合spec-id1

  "default-spec-id" : 1,"partition-specs" : [ {"spec-id" : 0,"fields" : [ {"name" : "ts_month","transform" : "month","source-id" : 3,"field-id" : 1000} ]}, {"spec-id" : 1,"fields" : [ {"name" : "ts_month","transform" : "month","source-id" : 3,"field-id" : 1000}, {"name" : "ts_day","transform" : "day","source-id" : 3,"field-id" : 1001} ]} ]

可以发现:

  1. v3.metadata.json发现分区演变是一种元数据操作,并不急于重写文件。
  2. 表分区可以在现有表中更新
  3. 多个分区的共同存在。
删除分区
        spark.sql("ALTER TABLE local.iceberg_db.table2 DROP PARTITION FIELD month(ts)");
数据层
元数据层
catalog
ts_month=2024-09
ts_month=2024-08
ts_day=2024-09-10
ts_day=2024-09-20
ts_day=2024-09-29
data files
parquet格式
data files
parquet格式
data files
parquet格式
data files
parquet格式
data files
parquet格式
v1.metadata.json
v2.metadata.json
v3.metadata.json
v4.metadata.json
v5.metadata.json
Manifest list
avro格式
Manifest list
avro格式
Manifest file
avro格式
Manifest file
avro格式
ceberg_db.table2

v5.metadata.jsonpartition-specs的变化,default-spec-id采用了新的分区组合spec-id2

  "default-spec-id" : 2,"partition-specs" : [ {"spec-id" : 0,"fields" : [ {"name" : "ts_month","transform" : "month","source-id" : 3,"field-id" : 1000} ]}, {"spec-id" : 1,"fields" : [ {"name" : "ts_month","transform" : "month","source-id" : 3,"field-id" : 1000}, {"name" : "ts_day","transform" : "day","source-id" : 3,"field-id" : 1001} ]}, {"spec-id" : 2,"fields" : [ {"name" : "ts_day","transform" : "day","source-id" : 3,"field-id" : 1001} ]} ]
删除数据
        spark.sql("DELETE FROM local.iceberg_db.table2  where id in (2)");
文件关系变化图
数据层
元数据层
catalog
ts_month=2024-09
ts_month=2024-08
ts_day=2024-08-29
ts_day=2024-09-10
ts_day=2024-09-20
ts_day=2024-09-29
status=2
status=0
data files
parquet格式
data files
parquet格式
data files
parquet格式
data files
parquet格式
data files
parquet格式
data files
parquet格式
v1.metadata.json
v2.metadata.json
v3.metadata.json
v4.metadata.json
v5.metadata.json
v6.metadata.json
Manifest list
avro格式
Manifest list
avro格式
Manifest list
avro格式
Manifest file
avro格式
Manifest file
avro格式
Manifest file
avro格式
Manifest file
avro格式
ceberg_db.table2

删除数据操作会触发数据文件的变化,此时目录ts_day=2024-08-29已经于ts_month=2024-08平级。ts_day=2024-08-29中的数据文件会保留删除之后的数据。

由于分区的变化后,旧的分区规则产生的数据文件发生了数据变化,会产生一个新清单文件(maifest file)中的,会对旧的数据文件进行索引,以上述为例,v6.metadata.json对应的清单列表文件(maifest list)中存储了一个清单文件(maifest file)即虚线框展示的,其中存储了两个datafile的引用,status=2代表删除,status=0代表文件已经存在。

小结

  • 每一个操作都会产生一个新的元数据文件(metadata.json),需要配置自动清理元数据文件
  • 所有一个文件都伴有一个.crc文件,小文件的问题怎么办?
  • Iceberg使用唯一的id来跟踪表中的每一列。添加列时,将为其分配一个新ID,以便不会错误地使用现有数据。
  • 分区演变时,是元数据的操作,数据文件的操作是滞后的,有数据变动时才会进行文件的重写。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/55105.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++ | Leetcode C++题解之第433题最小基因变化

题目&#xff1a; 题解&#xff1a; class Solution { public:int minMutation(string start, string end, vector<string>& bank) {int m start.size();int n bank.size();vector<vector<int>> adj(n);int endIndex -1;for (int i 0; i < n; i)…

爬虫及数据可视化——运用Hadoop和MongoDB数据进行分析

作品详情  运用Hadoop和MongoDB对得分能力数据进行分析&#xff1b;  运用python进行机器学习的模型调理&#xff0c;利用Pytorch框架对爬取的评论进行情感分析预测&#xff1b;  利用python和MySQL对网站的数据进行爬取、数据清洗及可视化。

快速实现AI搜索!Fivetran 支持 Milvus 作为数据迁移目标

Fivetran 现已支持 Milvus 向量数据库作为数据迁移的目标&#xff0c;能够有效简化 RAG 应用和 AI 搜索中数据源接入的流程。 数据是 AI 应用的支柱&#xff0c;无缝连接数据是充分释放数据潜力的关键。非结构化数据对于企业搜索和检索增强生成&#xff08;RAG&#xff09;聊天…

SpringBoot框架下体育馆管理系统的构建

1引言 1.1课题背景 当今时代是飞速发展的信息时代。在各行各业中离不开信息处理&#xff0c;这正是计算机被广泛应用于信息管理系统的环境。计算机的最大好处在于利用它能够进行信息管理。使用计算机进行信息控制&#xff0c;不仅提高了工作效率&#xff0c;而且大大的提高了其…

江协科技STM32学习- P19 TIM编码器接口

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

Redis篇(Java操作Redis)

目录 讲解一&#xff1a;简介 讲解二&#xff1a;Jedis Github 一、创建项目、 二、添加依赖 三、配置文件 四、Java连接Redis 五、通过Redis连接池获取连接对象并操作服务器 六、封装JedisUtil对外提供连接对象获取方法 七、Java操作Redis五种数据类型 1. 连接与释放…

助农小程序|助农扶贫系统|基于java的助农扶贫系统小程序设计与实现(源码+数据库+文档)

助农扶贫系统小程序 目录 基于java的助农扶贫系统小程序设计与实现 一、前言 二、系统功能设计 三、系统实现 5.1.1 农户管理 5.1.2 用户管理 5.1.3 订单统计 5.2.1 商品信息管理 5.3.1 商品信息 5.3.2 订单信息 5.3.3 商品评价 5.3.4 商品退货 四、数据库设计 1、…

水波荡漾效果+渲染顺序+简单UI绘制

创建场景及布置 创建新场景Main,在Main场景中创建一个plane物体&#xff0c;命名为WaterWavePla,具体数值及层级面板排布如下&#xff1a; 编写脚本 创建一个文件夹&#xff0c;用于存放脚本&#xff0c;命名Scripts,创建一个子文件夹Effect,存放特效相关脚本&#xff0c;创建…

WAF,全称Web Application Firewall,好用WAF推荐

WAF&#xff0c;全称Web Application Firewall&#xff0c;即Web应用防火墙&#xff0c;是一种网络安全设备&#xff0c;旨在保护Web应用程序免受各种Web攻击&#xff0c;如SQL注入、跨站脚本&#xff08;XSS&#xff09;、跨站请求伪造&#xff08;CSRF&#xff09;等。 WAF通…

前端面试经验总结2(经典问题篇)

谈谈你对前端的理解 前端主要负责产品页面部分的实现&#xff0c;是最贴近于用户的程序员。 基本工作要求&#xff1a; 1.参与项目&#xff0c;通过与团队成员&#xff0c;UI设计&#xff0c;产品经理的沟通&#xff0c;快速高质量的实现效果图&#xff0c;并能够精确到1px 2.做…

数学建模研赛总结

目录 前言进度问题四分析问题五分析数模论文经验分享总结 前言 本文为博主数学建模比赛第五天的内容记录&#xff0c;希望所写的一些内容能够对大家有所帮助&#xff0c;不足之处欢迎大家批评指正&#x1f91d;&#x1f91d;&#x1f91d; 进度 今天已经是最后一天了&#xf…

COMP 6714-Info Retrieval and Web Search笔记week2

tokenizer&#xff1a;分词器 右半部分&#xff1a;倒排索引 Westlaw AND&#xff08;&&#xff09;&#xff1a; 要搜索必须同时出现在文档中的两个或多个词语&#xff0c;请使用 AND&#xff08;&&#xff09;。例如&#xff0c;输入 narcotics & warrant&#x…

基于单片机的催眠电路控制系统

** 文章目录 前言一 概要功能设计设计思路 软件设计效果图 程序文章目录 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师&#xff0c;一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主…

【2024工业3D异常检测文献】CMDIAD: 基于跨模态蒸馏驱动的多模态工业异常检测

Incomplete Multimodal Industrial Anomaly Detection via Cross-Modal Distillation 1、Background 近年来&#xff0c;基于3D点云和RGB图像的多模态工业异常检测(IAD)研究强调了利用模态间的冗余性和互补性对于精确分类和分割的重要性。 在项目中&#xff0c;提出了CMDIAD方…

如何在算家云搭建MVSEP-MDX23(音频分离)

一、MVSEP-MDX23简介 模型GitHub网址&#xff1a;MVSEP-MDX23-music-separation-model/README.md 在 main ZFTurbo/MVSEP-MDX23-音乐分离模型 GitHub 上 在音视频领域&#xff0c;把已经发布的混音歌曲或者音频文件逆向分离一直是世界性的课题。音波混合的物理特性导致在没有…

js列表数据时间排序和取唯一值

1.取唯一值[...new Set(array)] const array [1, 2, 3, 2, 4, 5, 3, 5]; // 使用Set去除重复元素 const uniarray [...new Set(array)]; console.log(uniarray); // 输出: [1, 2, 3, 4, 5] 2.排序 var u [1,3,2,5,4]; var uu u.sort(); console.log(uu); var u [1,3…

【UE5】将2D切片图渲染为体积纹理,最终实现使用RT实时绘制体积纹理【第四篇-着色器投影-接收阴影部分】

上一章中实现了体积渲染的光照与自阴影&#xff0c;那我们这篇来实现投影 回顾 勘误 在开始本篇内容之前&#xff0c;我已经对上一章中的内容的错误进行了修改。为了确保不会错过这些更正&#xff0c;同时也避免大家重新阅读一遍&#xff0c;我将在这里为大家演示一下修改的…

算法分析——《二分查找》

&#x1f6e9;《二分查找》 &#x1f3a8;题目描述&#xff1a; 给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组 nums 和一个目标值 target &#xff0c;写一个函数搜索 nums 中的 target&#xff0c;如果目标值存在返回下标&#xff0c;否则返回 -1。 示例 …

Java基础(Arrays工具类)(asList()方法)(详细)

目录 一、Arrays工具类 &#xff08;1&#xff09;引言 &#xff08;2&#xff09;基本介绍 &#xff08;3&#xff09;主要功能&#xff08;提供的方法&#xff09; &#xff08;I&#xff09;排序&#xff08;Arrays.sort()&#xff09; &#xff08;II&#xff09;搜索(查找…

怎么给视频加片头片尾和字幕

在这个视觉内容爆炸的时代&#xff0c;一段精心制作的视频不仅能吸引眼球&#xff0c;更能传达深刻的情感与信息。而一个引人入胜的片头、一个温馨感人的片尾&#xff0c;以及恰到好处的字幕&#xff0c;无疑是提升视频质感的关键。那么新人要怎么给视频加片头片尾和字幕效果呢…