DB2在多节点部署场景下(尤其是DPF,即Database Partitioning Feature),数据会按照分布键的哈希值或范围规则打散到各个分区上。理想状态下每个分区承载的数据量大致相当,查询能够真正实现并行加速。但现实往往不这么理想:一旦某个分区的数据量或负载远超其他分区,整个并行计划的执行时间就被这个最慢的节点决定,这就是典型的数据倾斜问题。数据倾斜的隐蔽性很强,节点数量少时性能损失不明显,等到集群扩容或者数据量增长后才集中爆发,因此值得系统地梳理识别和处理方法。

一、数据倾斜的常见成因分析
第一类也是最普遍的成因是分布键选择不当。如果分布键选了性别、状态码、地区编码这类基数极低的列,哈希函数无论怎么计算,最终只能落到有限的几个桶上。例如一张几亿行的订单表用订单状态作为分布键,而订单状态只有五六种取值,那么最多只有几个分区有数据,其余分区完全空闲,并行能力形同虚设。
第二类成因是连接列与分布列不匹配。DPF环境下,两张表做连接时如果连接列恰好都是各自的分布键,数据库可以在各分区内本地完成连接,不需要表队列(Table Queue)在网络间搬运数据。反之,如果连接列不是分布列,就会产生大量跨分区的数据重分布动作,运行时某个分区可能瞬间接收到远超其他分点的数据量,形成执行期倾斜。
第三类成因相对隐蔽,包括空值过多、统计信息过期导致优化器误判分布情况,以及数据本身的热点特征(比如某个大客户的交易记录占全表三成)。这些情况在监控中往往表现为个别分区上的聚合或哈希操作耗时异常。
二、如何定位倾斜的分区和表
识别倾斜的第一步是看各分区的数据量分布。可以通过系统目录表和快照工具获取每个分区上每张表的实际行数,常用的方式是查询SYSCAT.TABLES结合分区函数,或者直接使用db2pd工具查看存储层信息。一个实用的SQL示例如下:
-- 查询指定表在各分区上的数据页分布情况
SELECT DATAPARTITIONNAME, ROWS, PAGESIZE
FROM TABLE(SYSPROC.ADMIN_GET_TAB_INFO('SCHEMA_NAME','ORDER_TABLE')) AS T;
除了静态数据量,还应该关注执行期的动态倾斜。快照监控中的表队列统计信息能反映查询运行时各分区间传输的数据量,如果发现某个分点的发送或接收量异常突出,基本可以断定执行计划中存在数据重分布热点。配合db2batch或解释工具输出的访问计划,可以进一步确认倾斜发生在哪一步操作,是哈希连接的构建端还是分组聚合的中间结果。
此外建议建立定期巡检机制,把各分区的行数比例记录下来形成趋势报表。倾斜往往是渐进式恶化的,有了历史数据才能判断是数据增长带来的自然偏移,还是业务模式变化导致的结构性问题,处理策略也完全不同。
三、分布键设计与重新分布处理
处理倾斜最根本的手段是重新设计分布键。理想的分布键应该满足三个条件:基数足够高(取值种类远超分区数)、值分布均匀、并且经常出现在大表连接条件中。对于订单类事实表,订单ID或者客户ID加订单日期的组合通常是不错的选择;对于维表,优先选择能与事实表形成本地连接的列。修改分布键可以使用REDISTRIBUTE操作:
-- 修改表的分布键并重新分布数据 ALTER TABLE order_table DISTRIBUTE BY HASH(cust_id, order_date); -- 执行数据重新分布,DB2会在各分区间搬运数据 REDISTRIBUTE DATABASE PARTITION GROUP pg_hash CONTINUE;
需要特别注意的是,REDISTRIBUTE是一个代价高昂的操作,会在分区之间大量搬运数据,期间锁表且产生大量日志,生产环境务必安排在维护窗口执行,并且提前评估各分区磁盘空间是否充足。对于分区数较多的集群,建议分批进行并随时监控进度。
如果暂时无法更换分布键,也有一些缓解手段。比如为热点键值增加随机后缀,将原本落在同一分区的热点数据人为打散;或者在查询层面利用谓词排除减少热点分区承担的扫描量。对于倾斜的聚合操作,可以考虑先在各分区做局部聚合,再汇总合并,避免把原始明细全部拉到协调节点。
四、统计信息与索引的配套优化
分布键调整之后,统计信息的更新同样关键。优化器依赖分布统计信息来判断数据在各分区的分布情况,如果统计信息过期,即使数据已经倾斜,优化器仍可能选择错误的执行策略。执行RUNSTATS时应收集列组统计信息和分位数统计,让优化器掌握真实的分布轮廓:
-- 收集表和索引的详细统计信息,包含分布统计 RUNSTATS ON TABLE schema_name.order_table WITH DISTRIBUTION AND DETAILED INDEXES ALL;
索引方面,在倾斜分区上合理使用本地索引能够减少扫描代价。DPF下每个分区维护自己的本地索引,因此热点分区的索引质量直接影响整体表现。同时要检查连接查询是否利用了分区一致性(Collocation),将频繁连接的表用相同的分布键放在同一分区组内,可以彻底消除跨节点数据传输,这比任何事后调优都更有效。
最后要强调持续监控的价值。数据倾斜不是一次性解决的问题,业务演进会不断制造新的热点。把分区数据量比例、表队列流量、各分区语句耗时纳入日常监控指标,设定告警阈值,才能在倾斜恶化到影响业务之前及时介入,保持多节点环境的并行性能长期稳定。