【问题标题】:wrapping postgresql commands in a transaction: truncate vs delete or upsert/merge在事务中包装 postgresql 命令:truncate vs delete 或 upsert/merge
【发布时间】:2023-12-08 17:59:01
【问题描述】:

我在 postgresql 9.1.3 中使用以下命令将数据从临时临时表移动到 webapp (geoserver) 中使用的表,所有这些都在同一个数据库中。然后删除临时表。

  1. TRUNCATE table_foo;

  2. INSERT INTO table_foo

    SELECT * FROM table_temp;

  3. DROP TABLE table_temp;

我想将其包装在事务中以允许并发。数据集小于 2000 行,截断比删除快。

  • 在事务中运行这些命令的最佳方式是什么?
  • 是否建议在 CTE 中创建函数或编写 UPSERT/MERGE 等?
  • 删除所有行然后从临时表批量插入而不是 TRUNCATE 会更好吗?
  • 在允许回滚 TRUNCATE 或 DELETE 的 postgres 中?
  • 临时表每天通过在 arcpy 中编写的 ETL 交付,如何在 postgres 中自动执行截断/删除/批量插入部分?
  • 我愿意使用 PL/pgsql、PL/python(或推荐用于 postgres 的 py)

目前我在临时登台表导入我的数据库后手动执行 sql 命令。

【问题讨论】:

    标签: postgresql plpgsql common-table-expression truncate plpython


    【解决方案1】:

    truncatedelete 都可以回滚(手册中有明确记录)。

    truncate - 由于其性质 - 在可见性方面有些奇怪。

    详见手册:http://www.postgresql.org/docs/current/static/sql-truncate.html(底部警告)

    如果您的应用程序可以接受table_foo 在该过程中为“空”的事实,则截断可能更好(再次参见手册中的大红框以获取解释)。如果不想让应用注意到,需要使用delete

    要在事务中运行这些语句,只需将它们合二为一:

    begin transaction;
    delete from table_foo;
    insert into ....
    drop table_temp;
    commit;
    

    您是否在函数中执行此操作取决于您。

    truncate/insert 将比delete/insert 更快,因为这样可以最大限度地减少生成的 WAL 数量。

    【讨论】:

    • 感谢您的建议。这效果很好。由于 MVCC 安全,我将使用 DELETE FROM vs TRUNCATE。您对使用 python 调用 psql 命令有什么建议或经验。我正在使用 pyodbc 并将事务放在 python 查询字符串中。虽然我听说过使用 psycopg2。
    • @EnzovsJacques:抱歉,我不会使用 Python。