【问题标题】:Postgresql - How to speed up for updating huge table(100 million rows)?Postgresql - 如何加快更新大表(1 亿行)?
【发布时间】:2017-03-02 07:22:53
【问题描述】:

我有两张大桌子:

Table "public.tx_input1_new" (100,000,000 rows) 

     Column     |            Type             | Modifiers
----------------|-----------------------------|----------
 blk_hash       | character varying(500)      |
 blk_time       | timestamp without time zone |
 tx_hash        | character varying(500)      |
 input_tx_hash  | character varying(100)      |
 input_tx_index | smallint                    |
 input_addr     | character varying(500)      |
 input_val      | numeric                     |

Indexes:
    "tx_input1_new_h" btree (input_tx_hash, input_tx_index) 

Table "public.tx_output1_new" (100,000,000 rows)

    Column    |          Type          | Modifiers
--------------+------------------------+-----------
 tx_hash      | character varying(100) |
 output_addr  | character varying(500) |
 output_index | smallint               |
 input_val    | numeric                |

Indexes:
    "tx_output1_new_h" btree (tx_hash, output_index)

我想通过另一个表来更新table1:

UPDATE tx_input1 as i
SET 
  input_addr = o.output_addr,
  input_val = o.output_val
FROM tx_output1 as o
WHERE 
  i.input_tx_hash = o.tx_hash
  AND i.input_tx_index = o.output_index;

在我执行这个 SQL 命令之前,我已经为这两个表创建了索引:

CREATE INDEX tx_input1_new_h ON tx_input1_new (input_tx_hash, input_tx_index);

CREATE INDEX tx_output1_new_h ON tx_output1_new (tx_hash, output_index);

我使用EXPLAIN 命令查看查询计划,但它没有使用我创建的索引。

完成此UPDATE 大约需要 14-15 小时。

里面有什么问题?

如何缩短执行时间,或调整我的数据库/表?

谢谢。

【问题讨论】:

  • Edit您的问题并添加执行计划(再次:formatted text
  • 好的。对不起。
  • 您的问题更多是关于:Why postgres is not using the index?
  • 我已经搜索过这个主题,但它无济于事。我认为这可能不是由错误的索引引起的。
  • 1) input_tx_hash 在任一表中包含多少个不同的值? 2) 这次更新实际上会改变多少条记录的值?

标签: performance postgresql sql-update sql-execution-plan


【解决方案1】:

由于您要连接两个大表并且没有条件可以过滤掉行,唯一有效的连接策略将是哈希连接,没有索引可以帮助。

首先将对其中一个表进行顺序扫描,从中构建哈希结构,然后对另一个表进行顺序扫描,并针对找到的每一行探测哈希值。任何索引对此有何帮助?

您可以预计这样的操作会花费很长时间,但有一些方法可以加快操作速度:

  • 在开始之前删除tx_input1 上的所有索引和约束。您的查询是索引根本没有帮助但实际上损害性能的示例之一,因为索引必须与表一起更新。完成UPDATE 后重新创建索引和约束。根据表上的索引数量,您可以期待获得不错的性能提升。

  • 使用SET 命令尽可能高地增加这一操作的work_mem 参数。哈希操作可以使用的内存越多,速度就越快。对于这么大的表,您最终可能仍会拥有临时文件,但您仍然可以期待获得不错的性能提升。

  • checkpoint_segments(或max_wal_size 从9.6 版起)增加到一个较高的值,以便在UPDATE 操作期间有更少的检查点。

  • 确保两个表上的表统计信息都是准确的,以便 PostgreSQL 能够对要创建的哈希桶的数量做出良好的估计。

UPDATE 之后,如果它影响大量行,您可以考虑在tx_input1 上运行VACUUM (FULL) 以消除导致的表膨胀。这将锁定表更长的时间,因此请在维护窗口期间执行此操作。它将减小表的大小,从而加快顺序扫描。

【讨论】:

  • 请问如何建hash结构表并做hash join?
  • 您不必这样做,数据库会为您完成。我刚刚向您解释了数据库如何执行您的连接,以便您了解如何加快它。
  • 哇!删除 25 个索引,将 work_mem 从 2 GB 设置为 4GB,将 checkpoint_timeout 从 5 分钟设置为 1 小时,将 max_wal_size 从 1 GB 设置为 30GB,将 7000 万行表的更新时间从 23 小时缩短到 30 分钟。谢谢!
猜你喜欢
  • 2018-03-29
  • 1970-01-01
  • 1970-01-01
  • 2019-08-20
  • 2021-07-17
  • 2012-11-30
  • 2016-12-11
  • 2010-09-26
  • 1970-01-01
相关资源
最近更新 更多