前言
spark操作iceberg之前先要配置spark catalogs,详情参考Iceberg与Spark整合环境配置。
Iceberg使用Apache Spark的DataSourceV2 API来实现数据源和catalog。
使用SQL查询
查询的时候表要按照:catalog.数据库.表名的格式
SELECT * FROM prod.db.table; -- catalog: prod, namespace: db, table: table
元数据表(如历史和快照)可以使用Iceberg表名作为命名空间。
例如,要从文件的元数据表中读取prod.db.table:
SELECT * FROM prod.db.table.files;
SQL查询的方式就和普通数据库没什么区别,只要把数据库.表名,前面加上一个catalog即可。
DataFrame查询
- 查询语法
dataframe查询iceberg表:
val df = spark.table("prod.db.table")
也可以通过DataFrameReader接口查询:
val df = spark.read.format("iceberg").load(table)
这里的table变量可以采用下面这几种形式:
- file:///path/to/table:在给定路径加载HadoopTable
- tablename:加载currentCatalog.currentNamespace.tablename
- catalog.tablename:通过指定的catalog加载
- namespace.tablename:从当前的catalog中通过namespace.tablename
- catalog.namespace.tablename:通过指定的catalog加载namespace.tablename
- namespace1.namespace2.tablename:从当前catalog加载namespace1.namespace2.tablename
以上列表是按优先顺序排列的。例如:匹配的catalog将优先于任namespace解析。
上面只是列出了table字段可以写的各种方式,但是我们大部分时候用的是:catalog.数据库.表名
- 查询示例
- 建表
create table prod.default.tb_student (id int,name string,age int) using iceberg
- 插入测试数据
insert into prod.default.tb_student values (1,'zs',18),(2,'ls',19),(3,'ww',20)
- 创建SparkSession
SparkSession spark = SparkSession.builder().appName(LocalIcebergTemplate.class.getSimpleName())
.master("local")
.config("spark.sql.catalog.prod", "org.apache.iceberg.spark.SparkCatalog")
.config("spark.sql.catalog.prodg.type", "hive")
.config("spark.sql.catalog.prod.warehouse", "hdfs://nameservice/warehouse/hive")
.config("spark.sql.extensions", "org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions")
.getOrCreate();
- spark.sql查询
spark.sql("select * from iceberg.ic_wfcf_mart.tb_student").show();
- spark.table查询
spark.table("prod.default.tb_student").show();
当然我们可以在代码最开始就选择好当前的catalog,那么后面查询的时候table字段只需要传入:数据库.表名即可。比如在查询代码之前执行:
spark.sql(“use prod”);
- DataFrameReader查询
spark.read().format("iceberg").load("prod.default.tb_student").show();
查询快照
为了在DataFrame API中选择特定的表快照或某个时间的快照,Iceberg支持四种Spark读取选项:
- snapshot-id:选择一个特定的表快照
- as-of-timestamp:选择时间戳处的当前快照,以毫秒为单位
- branch:选择指定分支的头部快照。注意,当前分支不能与时间戳组合。
- tag:选择与指定标记关联的快照。标记不能与时间戳组合在一起。
- SQL查询表的快照
spark.sql("select * from prod.default.tb_student.snapshots").show();
可以看到该表所有的快照信息:提交时间、快照id、父id、快照操作、manifest_list和汇总。
- DataFrameReader查询指定快照id表的数据
这里我们为了说明查询指定id后的数据,我们再插入一条数据,这样会生成新的快照id,而我们指定其中一个快照id
insert into iceberg.ic_wfcf_mart.tb_student values (4,'lily',18),(5,'lucy',19),(6,'jack',20)
查询所有快照:
spark.sql("select * from iceberg.ic_wfcf_mart.tb_student.snapshots").show();
查询指定的快照id的数据:
spark.read().option("snapshot-id", 8182683976426523948L)
.format("iceberg").load("prod.default.tb_student").show();
- DataFrameReader查询指定起止快照id表的数据
// get the data added after start-snapshot-id (10963874102873L) until end-snapshot-id (63874143573109L)
spark.read
.format("iceberg")
.option("start-snapshot-id", "10963874102873")
.option("end-snapshot-id", "63874143573109")
.load("path/to/table")
- start-snapshot-id:增量扫描的起始快照ID(不包含)。
- end-snapshot-id:增量扫描结束快照ID(含)。这是可选的。省略它将默认为当前快照。
(start-snapshot-id,end-snapshot-id]
查询表历史
spark.sql("select * from prod.default.tb_student.history").show();
查询表data files
spark.sql("select * from prod.default.tb_student.files").show();
查询Manifests
spark.sql("select * from prod.default.tb_student.manifests").show(false);
查询Entries
显示数据和删除文件的所有表当前清单项。
spark.sql("select * from prod.default.tb_student.entries").show(false);
查询所有分区
SELECT * FROM prod.db.table.partitions;
查询删除文件的位置
SELECT * from prod.db.table.position_deletes;
查询表的所有Data Files
SELECT * FROM prod.db.table.all_data_files;
查询所有删除的文件
SELECT * FROM prod.db.table.all_delete_files;
查询所有Entries
SELECT * FROM prod.db.table.all_entries;
查询所有Manifests
SELECT * FROM prod.db.table.all_manifests;
参考文献
spark queries
https://bbs.huaweicloud.com/blogs/363841