为海量数据表创建列存索引(IMCI)时,通常需要消耗大量时间,这会严重影响数据分析的准备效率。PolarDB PostgreSQL版提供的并行创建索引功能,能够充分利用多核CPU资源,将多个工作进程(Worker)并行投入到索引构建任务中,从而大幅缩短大表的索引创建时间,帮助您快速为数据仓库或大型业务表启用分析加速能力。
适用范围
支持的PolarDB PostgreSQL版的版本:
PostgreSQL 14,且内核小版本需为2.0.14.22.49.0及以上版本。
PostgreSQL 16,且内核小版本需为2.0.16.14.21.0及以上版本。
PostgreSQL 18,且内核小版本需为2.0.18.6.5.0及以上版本。
注意事项
并行度上限:
polar_csi.build_index_parallel的设置值不能超过实例的max_parallel_workers参数值。您可以通过SHOW max_parallel_workers;命令查询当前上限。内存消耗:每个并行工作进程预计会额外消耗约 500MB 的内存。请在增加并行度前,评估并确保您的实例有充足的可用内存。
主键列约束:CSI 索引必须包含表的所有主键列,否则创建索引时会返回错误
ERROR: All primary key columns must be included in the CSI index.。如果表定义了主键,请在CREATE INDEX语句的列列表中显式包含所有主键列。
工作原理
并行创建索引功能基于PostgreSQL的parallel worker框架。当您发起一个创建列存索引的请求时,其内部工作流程如下:
启动并行任务:主导进程(Leader)根据参数
polar_csi.build_index_parallel的设置,向系统申请指定数量的并行工作进程(Parallel Worker)。数据分片:Leader进程将目标表的数据在逻辑上划分为多个分片,并将这些分片均匀分配给各个Worker进程。
并行构建:每个Worker进程独立扫描其负责的数据分片,并对数据进行排序、转换和压缩,在内存中构建出局部的、临时的列存索引片段。
归并结果:待所有Worker进程完成各自任务后,Leader进程会将所有临时的索引片段归并(Merge),形成一个最终完整、可用的列存索引。
操作指南
步骤一:评估资源并设置并行度
根据集群的可用资源,合理设置并行度以达到最佳性能,避免因资源不足导致任务失败或影响其他业务。
内存评估:预估总消耗内存 ≈
polar_csi.build_index_parallel 值 × 500 MB。CPU评估:建议将并行度设置为集群CPU核数的1/4到1/2作为起点,以在加速效果和系统负载之间取得平衡。
设置并行度:
-- 将当前会话的并行度设置为8 SET polar_csi.build_index_parallel TO 8;
步骤二:执行索引创建
根据业务场景选择合适的创建方式,在性能和业务连续性之间做出选择。
方案一:离线创建(速度最快)
此方式在创建过程中会持有排他锁,阻塞对表的写入操作。适用于可在业务低峰期或维护窗口内执行的场景,例如数据初始化。
CREATE INDEX idx_csi_orders ON orders USING csi (id, column1, column2);其中
id为表orders的主键列。CSI 索引要求列列表中包含所有主键列,否则创建会失败。方案二:在线创建(不阻塞写入)
此方式使用
CONCURRENTLY关键字,允许在创建索引的同时进行数据写入,保障业务连续性。适用于对业务连续性要求高的生产环境。CREATE INDEX CONCURRENTLY idx_csi_orders_concurrently ON orders USING csi (id, column1, column2);其中
id为表orders的主键列。CSI 索引要求列列表中包含所有主键列,否则创建会失败。
性能与调优
以下是在50 GB数据量上进行的性能测试,结果展示了不同并行度下的耗时和加速比。
并行度 | 耗时 | 加速比 |
1 | 25分44秒 | 1.00 |
4 | 09分31秒 | 2.70 |
8 | 05分06秒 | 5.05 |
16 | 02分48秒 | 9.19 |
32 | 01分25秒 | 18.16 |
性能分析与调优建议:
收益递减:从上表可以看出,加速比并非随并行度线性增长。当并行度过高时,进程间协作、IO瓶颈以及最终的归并阶段开销会逐渐凸显,导致边际效益递减。
并行度选择:
常规建议:建议从集群CPU核数的1/4到1/2开始测试,并根据实际的CPU和IO负载进行调整。
IO密集型场景:如果监控发现IO使用率已达瓶颈,而CPU尚有空闲,应适当降低并行度,避免过多的IO争抢。
CPU密集型场景:如果IO资源充裕,但CPU未达到瓶颈,可适当增加并行度,但注意不要超过
max_parallel_workers的值。