DB2 的数据库分区功能(Database Partitioning Feature,简称 DPF)是一种内置的水平分片方案。当单表数据增长到数亿行之后,单节点数据库的存储、I/O 和 CPU 都会遇到瓶颈,此时依靠传统的索引优化和 SQL 调优往往收效有限。DB2 DPF 允许将同一张表的数据根据分布键哈希后分布到多个分区节点上,每个分区独立管理自己那部分数据,SQL 语句则不需要做任何改动,协调分区会自动把查询下发到各个分区并行执行,最后汇总结果。下面这张架构图展示了多个分区并行处理请求的基本形态。

要启用 DPF,首先需要在实例层面配置多个分区。DB2 使用 db2nodes.cfg 文件定义所有分区的主机名和逻辑端口,每个分区拥有独立的缓冲池、日志和临时空间。创建数据库后,数据库管理员可以定义分区组、表空间以及带分布键的表。整个过程对应用连接字符串也没有影响,应用仍然只连接到一个协调分区。
DB2 分片的核心机制:DPF 与分布键
DPF 的底层思路是把一个逻辑数据库的运算负载拆到多个物理节点上。一个数据库分区实际上就是一套完整的 DB2 实例资源,包含自己的内存区域、事务日志和存储路径。客户端连接到的节点称为协调分区,协调分区负责解析 SQL、生成执行计划并把子任务发送给其他分区。其他分区在本地完成扫描、过滤和聚合后,把中间结果传回协调分区做最终合并。
分布键决定了每一行数据落在哪个分区。建表时可以使用 DISTRIBUTE BY HASH 子句指定一个或多个列作为分布键。DB2 对这些列的值做哈希运算,再根据分区数取模,得到目标分区号。如果建表时没有指定分布键,DB2 会使用表定义中的第一个主键列;如果没有主键,则使用第一个非 LOB 列。这种默认行为在真实业务中很容易导致数据倾斜,所以创建分片表时必须显式评估并指定分布键。
-- 创建数据库后,先建立一个包含所有分区的分区组 CREATE DATABASE PARTITION GROUP allparts ON ALL DBPARTITIONNUMS; -- 在分区组上创建表空间 CREATE TABLESPACE ts_sharded IN allparts MANAGED BY AUTOMATIC STORAGE; -- 创建带分布键的表 CREATE TABLE order_main ( order_id BIGINT NOT NULL, customer_id BIGINT NOT NULL, order_date DATE NOT NULL, amount DECIMAL(12,2), status VARCHAR(20), PRIMARY KEY (order_id, customer_id) ) IN ts_sharded DISTRIBUTE BY HASH (customer_id);
上面的例子把 customer_id 作为分布键。对于订单表来说,按客户维度做等值查询非常常见,例如查询某个客户的所有订单,DB2 可以直接定位到对应分区,避免扫描全部分区。需要注意的是,分布键一旦确定,后续不能通过 ALTER TABLE 修改,只能重建表并搬迁数据。
分片环境下的表设计与数据倾斜优化
分布键的选择直接决定分片效果。一个好的分布键应当具备足够高的基数,让数据尽量均匀地散列到各个分区。例如 customer_id、order_id 这类唯一或接近唯一的字段通常比 status、province 等低基数字段更适合。低基数字段作为分布键会导致某些分区数据量远大于其他分区,造成查询时个别节点执行时间过长,所有分区都要等待最慢的那一个,也就是典型的数据倾斜问题。
检测数据倾斜可以通过 DB2 提供的分区号函数来实现。DBPARTITIONNUM 函数返回某一行所在的分区号,结合分组统计就能看到每个分区的行数分布。如果某个分区的行数明显高于平均值,就需要重新考虑分布键。下面的 SQL 可以快速检查订单表在各个分区的数据量:
SELECT DBPARTITIONNUM(customer_id) AS partition_num,
COUNT(*) AS row_count
FROM order_main
GROUP BY DBPARTITIONNUM(customer_id)
ORDER BY partition_num;
如果已经出现倾斜,临时可以采用一些补救措施。比如使用随机分布列把数据打散,但这样会损失分区裁剪能力,所有查询都要访问全部分区;更合理的做法是选择包含多个列的组合分布键,例如 customer_id 与 order_date 的组合,在不降低均匀性的前提下保留局部亲和性。实际项目中,分布键设计应当在建表前通过生产数据样本做哈希模拟,而不是上线后被动调整。
还需要注意主键和唯一约束在分片环境中的限制。DB2 DPF 要求主键或唯一索引必须包含分布键,否则无法保证全局唯一性。这意味着如果 order_id 是全局唯一主键,但分布键选择了 customer_id,主键定义必须写成 PRIMARY KEY (order_id, customer_id),就像前面示例那样。如果业务上确实需要按 order_id 唯一,而没有包含 customer_id 的唯一索引,DB2 会拒绝创建。
DB2 分片查询执行与运维注意事项
分片环境下的 SQL 执行过程与单分区有很大不同。协调分区收到查询后,会分析谓词是否包含分布键。如果 WHERE 条件中出现了分布式键的等值判断,DB2 可以做分区裁剪,只把任务发给一个或少数几个分区,这种查询效率最高。如果查询条件不包含分布键,例如按订单日期范围统计所有客户,协调分区就必须把任务广播到所有分区,然后在各分区并行扫描、聚合,最后再汇总。此时网络传输开销和协调分区的合并压力会明显增加。
执行计划中的数据传输操作符能够帮助判断分片查询是否高效。使用 db2expln 工具生成执行计划后,可以观察是否存在 BT(Broadcast)、DT(Data Transmission)等操作符。BT 出现意味着有数据从协调分区向所有分区广播,DT 表示分区之间需要交换中间结果。通过调整分布键或改写 SQL,可以减少这类跨分区传输。例如把常用过滤条件尽量设计成分布键的一部分,是分片调优最有效的手段之一。
db2 connect to testdb db2expln -d testdb -g -o order_plan.txt -q 'SELECT * FROM order_main WHERE customer_id = 10086'
备份与恢复也需要从整个数据库的角度考虑。DB2 的在线备份会同时备份所有分区的数据,恢复时要求所有分区都处于可用状态,不能只恢复单个分区。扩容操作则相对复杂,新增分区后需要使用 REDISTRIBUTE DATABASE PARTITION GROUP 命令重新分布数据,这个过程会锁表并产生大量 I/O,通常需要在维护窗口执行。
与应用层 Sharding 相比,DB2 DPF 的最大优势是对应用透明,SQL 和事务逻辑不需要改动,适合已有大型 DB2 数据库的平滑扩展。但 DPF 需要额外的硬件资源、DB2 企业版许可证以及专业的运维能力,成本不低。应用层 Sharding 则在数据库外部通过中间件或客户端路由实现,灵活度高,但需要处理跨分片查询、分布式事务和全局唯一 ID 等复杂问题。如果企业已经深度使用 DB2,且数据量确实达到单节点瓶颈,DPF 是投入产出比较高的选择;如果只是部分表较大且业务可拆,应用层 Sharding 可能更轻量。
DB2分片数据库ShardingDB2 DPF修改时间:2026-09-22 01:34:00