Postgres 多列索引需要很长时间才能完成

Postgres multi-column index is taking forever to complete

我有一个 table 大约有 270,000,000 行,这就是我创建它的方式。

CREATE TABLE init_package_details AS
    SELECT pcont.package_content_id as package_content_id,
                    pcont.activity_id as activity_id,
                    pc.org_id as org_id,
                    pc.bed_type as bed_type,
                    pc.is_override as is_override,
                    pmmap.package_id as package_id,
                    pcont.activity_qty as activity_qty,
                    pcont.charge_head as  charge_head,
                    pcont.activity_charge as charge,
                    COALESCE(pc.charge,0) - COALESCE(pc.discount,0) as package_charge 
    FROM a pc
                    JOIN b od ON
                                (od.org_id = pc.org_id AND od.status='A')
                    JOIN c pm ON 
                                (pc.package_id=pm.package_id)
                    JOIN d pmmap ON
                                (pmmap.pack_master_id=pm.package_id)
                    JOIN e pcont ON 
                                (pcont.package_id=pmmap.package_id);

我需要在 init_package_details table.

上建立索引

这个 table 大约需要 5-6 分钟创建。

我已经创建了 btree 索引,

CREATE INDEX init_package_details_package_content_id_idx 
   ON init_package_details(package_content_id);`

这需要 10 分钟(比创建和填充 table 本身 的时间还多)

并且,当我创建另一个索引时,

CREATE INDEX init_package_details_package_act_org_bt_id_idx 
   ON init_package_details(activity_id,org_id,bed_type);

它只是冻结并需要很长时间才能完成。我等了大约 30 分钟才手动取消它。

以下是来自 iotop -o 的统计数据,如果有帮助,

有人可以解释为什么会这样吗?无论如何,我可以在这里加速索引创建吗?

编辑 1:没有其他连接访问 table。并且,pg_stat_activity 在整个 运行 时间内显示 active 作为状态。这发生在事务内部(这发生在 BEGINCOMMIT 之间,它在同一个 .sql 文件中包含许多其他脚本)。

编辑 2:

 postgres=# show work_mem ;
 work_mem
----------
 5MB
(1 row)

postgres=# show maintenance_work_mem;
 maintenance_work_mem
----------------------
 16MB

建立索引需要很长时间,这是正常的。

如果您在 I/O 上没有瓶颈,您可能在 CPU 上。

有几点可以提高性能:

  • 设置maintenance_work_mem很高。

  • 使用 PostgreSQL v11 或更高版本,可以使用多个并行工作器。