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
的统计数据,如果有帮助,
- 当我创建时 table 平均大约 110-120 MB/s(这就是在 5-6 分钟内插入 2.7 亿行的方式)
- 当我创建 First Index 时,它的平均值在 70 左右 MB/s
- 在第二个索引上,它在 5-7 处呈蜗牛状移动 MB/s
有人可以解释为什么会这样吗?无论如何,我可以在这里加速索引创建吗?
编辑 1:没有其他连接访问 table。并且,pg_stat_activity
在整个 运行 时间内显示 active
作为状态。这发生在事务内部(这发生在 BEGIN
和 COMMIT
之间,它在同一个 .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 或更高版本,可以使用多个并行工作器。
我有一个 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
的统计数据,如果有帮助,
- 当我创建时 table 平均大约 110-120 MB/s(这就是在 5-6 分钟内插入 2.7 亿行的方式)
- 当我创建 First Index 时,它的平均值在 70 左右 MB/s
- 在第二个索引上,它在 5-7 处呈蜗牛状移动 MB/s
有人可以解释为什么会这样吗?无论如何,我可以在这里加速索引创建吗?
编辑 1:没有其他连接访问 table。并且,pg_stat_activity
在整个 运行 时间内显示 active
作为状态。这发生在事务内部(这发生在 BEGIN
和 COMMIT
之间,它在同一个 .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 或更高版本,可以使用多个并行工作器。