数据分区

本文将介绍分区表的三种管理策略。

分区表(Partitioned Tables)

在 Fluss 中,分区表根据一个或多个分区键(partition keys)来组织数据,为大型数据集的查询性能提升和可管理性提供了一种有效方式。通过分区,系统可以将数据划分为不同的片段,每个片段对应特定的分区键值。

对于分区表,Fluss 支持以下三种分区管理策略:

  • 手动管理分区:用户可以手动创建新分区或删除已有分区。如需了解如何创建或删除分区,请参见管理分区

  • 自动管理分区:分区会根据建表时配置的自动分区规则自动生成,过期的分区也会被自动清理,确保数据不会无限增长。详见自动分区

  • 动态创建分区:分区会根据写入表中的数据动态创建。详见动态分区

这三种策略是正交的,可以在同一张表上共存。

多字段分区表(Multi-Field Partitioned Tables)

分区表(无论是主键表还是日志表),都支持基于多个字段配置分区键。这种方式允许用户通过字段值的组合来划分数据,从而实现更细粒度的数据组织、管理和查询优化。

例如,在一个订单(Order)主键表中,可以将分区键定义为 (date, region)。数据将会存储在与具体组合对应的分区中,如 date=2025-04-05, region=US。在流式查询中,用户可以通过对数据进行过滤(如 region=US)来利用分区裁剪(partition pruning),通过分区下推(partition pushdown)提升读取性能。

分区表的主要优势

  • 提升查询性能:通过限制查询范围到特定分区,系统读取的数据量减少,从而降低了查询执行时间。

  • 数据组织更清晰:分区帮助从逻辑上组织数据,使其更容易管理和查询。

  • 更好的扩展性:将大数据集划分为更小、更易管理的块,提升了系统的可扩展性。

限制条件

  • 分区键的类型必须为 STRING 类型。

  • 对于自动分区表,分区键可以是一个或多个字段。如果表只有一个分区键,则支持自动创建分区和自动过期清理;如果有多个分区键,则仅支持自动过期清理。

  • 如果该表为主键表,分区键必须是主键的一个子集。

  • 自动分区规则只能在创建分区表时配置,不支持在建表后修改自动分区规则。

自动分区

示例

自动分区规则通过表选项进行配置。以下示例展示了如何使用 Flink SQL 创建一个名为 site_access 的表,该表支持自动分区。

CREATE TABLE site_access(
  event_day STRING,  --分区键
  site_id INT,       --网站ID  
  city_code STRING,  --城市编号  
  user_name STRING,  --用户名 
  pv BIGINT,         --页面访问次数 
  PRIMARY KEY(event_day, site_id) NOT ENFORCED 
) PARTITIONED BY (event_day) WITH (
  'table.auto-partition.enabled' = 'true',            --启用自动分区 
  'table.auto-partition.time-unit' = 'YEAR',          --时间粒度为年 
  'table.auto-partition.num-precreate' = '5',         --预创建5个分区 
  'table.auto-partition.num-retention' = '2',         --保留两个历史分区 
  'table.auto-partition.time-zone' = 'Asia/Shanghai'  --时区为上海 
);

在此示例中,当自动分区发生时(Fluss 会在后台定期对所有表进行操作),将以 YEAR 为分区粒度预创建四个分区,并保留两个历史分区。时区设置为 Asia/Shanghai。

表参数

参数

类型

是否必填

默认值

备注说明

table.auto-partition.enabled

Boolean

false

是否为表启用自动分区。默认禁用。当自动分区启用时,表的分区将自动创建。

table.auto-partition.key

String

此配置定义了在表使用多个分区键时用于自动分区的时间分区键。自动分区利用基于时间的分区键来自动处理分区,包括创建新分区和删除过时分区,通过将分区的时间值与当前系统时间进行比较。如果表使用多个分区键(例如复合分区策略),此功能确定哪个键应作为自动分区决策的主要时间维度。如果表只有一个分区键,则无需配置此项。否则,必须指定。

table.auto-partition.time-unit

ENUM

DAY

自动创建分区的时间粒度。默认值为 'DAY'。有效值为 'HOUR', 'DAY', 'MONTH', 'QUARTER', 'YEAR'。如果值为 'HOUR',自动创建的分区格式为 yyyyMMddHH。如果值为 'DAY',自动创建的分区格式为 yyyyMMdd。如果值为 'MONTH',自动创建的分区格式为 yyyyMM。如果值为 'QUARTER',自动创建的分区格式为 yyyyQ。如果值为 'YEAR',自动创建的分区格式为 yyyy。

table.auto-partition.num-precreate

Integer

2

每次自动分区检查时预创建的分区数量。例如,如果当前检查时间为 2024-11-11 且配置值为 3,则将预创建分区 20241111, 20241112, 20241113。如果任何一个分区已存在,则跳过创建该分区。默认值为 2,表示将预创建 2 个分区。如果 'table.auto-partition.time-unit' 为 'DAY'(默认),则一个预创建分区为今天,另一个为明天。对于具有多个分区键的分区表,不支持预创建,如果未显式指定,则在创建表时会自动设置为 0。

table.auto-partition.num-retention

Integer

7

每次自动分区检查时保留的历史分区数量。例如,如果当前检查时间为 2024-11-11,时间单位为 DAY,且配置值为 3,则将保留历史分区 20241108, 20241109, 20241110。早于 20241108 的分区将被删除。默认值为 7。

table.auto-partition.time-zone

String

系统时区

自动分区的时区,默认与系统时区相同。

分区生成规则

自动分区表的时间单位 auto-partition.time-unit 可以取值为 HOUR, DAY, MONTH, QUARTER 或 YEAR。自动分区将使用以下格式创建分区。

时间单位

分区格式

示例

HOUR

yyyyMMddHH

2024091922

DAY

yyyyMMdd

20240919

MONTH

yyyyMM

202409

QUARTER

yyyyQ

20241

YEAR

yyyy

2024

Fluss 集群配置

以下是 Fluss 集群与自动分区相关的配置项。

选项

类型

默认值

描述

auto-partition.check.interval

Duration

10 分钟

自动分区检查的间隔时间。默认设置为 10 分钟,意味着每 10 分钟检查一次表分区状态,以查看是否符合自动分区条件。如果不符合条件,将自动创建或删除分区。

动态分区

动态分区是客户端默认启用的功能,允许客户端根据写入表的数据自动创建分区。当分区集事先未知时,此功能尤其有价值,无需手动创建分区。在处理多字段分区时,此功能也特别有用,因为自动分区目前仅支持单字段分区创建。

说明

动态创建的分区数量也受 Fluss 集群上配置的 max.partition.num 和 max.bucket.num 限制。

  • max.partition.num 默认值 1000, 代表每张分区表最多能创建的分区数。

  • max.bucket.num 默认值128000, 代表每张表最多能支持的总 bucket 数(即 分区数 x 分桶数)。

客户端选项

选项

类型

是否必填

默认值

描述

client.writer.dynamic-create-partition.enabled

Boolean

true

是否启用客户端写入器的动态分区创建。启用后,如果分区在数据写入时不存在,将自动创建新分区。

动态分区创建示例

步骤一:创建示例表

在左侧导航栏,数据开发 > 数据查询中,新建空白的数据查询脚本,输入以下SQL创建一张以ds列为分区键的分区表。

CREATE TABLE IF NOT EXISTS `fluss-demo`.fluss.table_enable_dynamic_partition
(
    id    BIGINT
    ,name STRING
    ,dt   STRING
)
PARTITIONED BY (dt)
WITH (
    'client.writer.dynamic-create-partition.enabled' = 'true'
)
;

验证表当前的分区

SHOW PARTITIONS `fluss-demo`.fluss.table_enable_dynamic_partition;

查询结果表明表的分区列表为空。

image

步骤二:动态插入数据

运行下列SQL,向不存在的分区插入数据。

INSERT INTO `fluss-demo`.fluss.table_enable_dynamic_partition values(1, 'hello', '20250701');

步骤三:验证分区被动态创建

再次执行SHOW PARTITIONS命令验证分区已经被动态创建。

image