【问题标题】:Postgres multi-column index is taking forever to completePostgres 多列索引需要很长时间才能完成
【发布时间】:2019-07-12 04:35:05
【问题描述】:

我有一个包含大约 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 表上建立索引。

此表在大约 5-6 分钟时创建。

我已经创建了类似的 btree 索引,

CREATE INDEX init_package_details_package_content_id_idx 
   ON init_package_details(package_content_id);`

这需要 10 分钟(超过创建和填充表格本身的时间

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

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

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

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

  • 当我创建表时,平均速度约为 110-120 MB/s(这就是在 5-6 分钟内插入 2.7 亿行的方式)
  • 当我创建第一个索引时,它的平均速度约为 70 MB/s
  • 在第二个索引上,它以 5-7 MB/s 的速度缓慢前进

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

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

编辑2:

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

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

【问题讨论】:

  • 表是否被其他会话/连接访问?也许 CREATE INDEX 只是在等待一个锁?您可以检查pg_stat_activity 以查看 DDL 是否正在等待某些东西。如果您关闭自动提交:您是否正确提交了所有内容?
  • 没有。没有其他会话访问该表。 pg_stat_activity 显示“活跃”
  • 你的 work_memmaintenance_work_mem 有多大? (show work_mem;show maintenance_work_mem; 会告诉你)。创建索引需要对值进行排序,如果在磁盘上完成,这将需要一段时间。尽量增加它们。
  • 我已将它们添加到编辑中。我不确定要设定的数字。如果你能帮我写一些这篇文章会很有帮助。

标签: postgresql indexing query-performance b-tree-index


【解决方案1】:

构建索引需要很长时间,这很正常。

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

有几件事可以提高性能:

  • maintenance_work_mem 设置得非常高。

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

【讨论】:

  • 谢谢@Laurenz!我尝试将 maintenance_work_mem 设置为 512 MB。然后,索引创建几乎在 15 分钟内完成。
猜你喜欢
  • 1970-01-01
  • 2018-02-07
  • 2016-07-30
  • 2013-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多