分区演进是 Apache Iceberg 提供的一项强大功能,允许在不重写数据的情况下动态更改表的分区策略。这一特性革新了传统大数据系统中分区变更的方式,大大提高了灵活性和运维效率。
Iceberg表分区可以在不需要重写现有表的情况下更新,因为查询不直接引用分区值。当我们更新分区时,早期的旧数据保持不变。每个分区版本的元数据分别保存。
在以下部分中,我们将看到如何根据需要就地演变表分区。
目前,我们的表按年份分区。
show_tables_files(ICEBERG_SALES_TABLE)
现在,假设2002年的销售量增长了10倍,因此我们需要将分区从销售年份更新为销售月份。我们需要首先删除years(ws_sales_time)
分区字段,然后添加一个新的分区字段months(ws_sales_time)
。
%%sql
ALTER TABLE ${ICEBERG_DB}.${ICEBERG_SALES_TABLE} DROP PARTITION FIELD years(ws_sales_time)
%%sql
ALTER TABLE ${ICEBERG_DB}.${ICEBERG_SALES_TABLE} ADD PARTITION FIELD months(ws_sales_time)
通过以下查询验证分区已更改为months(ws_sales_time)
。
spark.sql(f"""
DESCRIBE TABLE {ICEBERG_DB}.{ICEBERG_SALES_TABLE}
"""
).show(truncate=False)
看到当前表数据没有任何变化。这是因为分区演变是一个元数据操作,不会急切地重写文件:
show_tables_files(ICEBERG_SALES_TABLE)
新分区将对所有新数据生效。让我们插入2002年的数据进行验证。
%%sql
INSERT INTO ${ICEBERG_DB}.${ICEBERG_SALES_TABLE}
SELECT *
FROM spark_catalog.${TPC_DS_DATABASE}.${TPC_DS_SALES_TABLE} where year(ws_sales_time) = 2002
现在让我们检查我们的表数据文件夹。
show_tables_files(ICEBERG_SALES_TABLE)
我们可以看到2000年之前的数据是按年份分区的。从2002年开始,表改为按月份分区。两种分区布局能够在同一个表中共存。
通过以下查询,我们计算2000年1月1日和2002年1月1日的不同订单数量。通过隐藏分区,只检查特定分区(ws_sales_time_year=2000和ws_sales_time_month=2002-01)。
%%sql
SELECT COUNT(DISTINCT(ws_order_number)) AS num_orders, year(ws_sales_time) as year, month(ws_sales_time) as month
FROM ${ICEBERG_DB}.${ICEBERG_SALES_TABLE}
WHERE (ws_sales_time >= TIMESTAMP('2000-01-01 00:00:00') AND ws_sales_time < TIMESTAMP('2000-01-02 00:00:00')) OR (ws_sales_time >= TIMESTAMP('2002-01-01 00:00:00') AND ws_sales_time < TIMESTAMP('2002-01-02 00:00:00'))
GROUP BY year(ws_sales_time), month(ws_sales_time)
ORDER BY year(ws_sales_time), month(ws_sales_time)
Iceberg 的分区演进能力是其数据管理优势的关键体现,为数据湖的长期维护和优化提供了前所未有的灵活性,使表结构能够随着业务需求的变化而平滑演进。