VACUUM 不能从函数或多命令字符串执行

Posted

技术标签:

【中文标题】VACUUM 不能从函数或多命令字符串执行【英文标题】:VACUUM cannot be executed from a function or multi-command string 【发布时间】:2014-03-12 20:35:44 【问题描述】:

我使用 PL/pgSQL 编写了一个脚本,在 pgAdmin III 中运行。该脚本删除现有的数据库内容,然后为所需的测试场景(通常是各种类型的负载测试)添加一堆“样本”数据。加载数据后,我想对受影响的表进行“真空分析”,以从已删除的记录中恢复空间并准确反映新内容。

我可以使用各种解决方法(例如,手动执行 VACUUM ANALYZE,在脚本中包含用于各种结构的 drop/create 语句等)但是,我真正想做的是:

DO $$
BEGIN
  -- parent table
  FOR i IN 1..10000 LOOP
    INSERT INTO my_parent_table( ... ) VALUES ...;
  END LOOP;

  VACUUM ANALYZE my_parent_table;

  -- child table
  FOR i IN 1..50000 LOOP
    INSERT INTO my_child_table( ... ) VALUES ...;
  END LOOP;

  VACUUM ANALYZE my_child_table;
END;
$$;

当我运行它时,我得到:

ERROR:  VACUUM cannot be executed from a function or multi-command string

然后我尝试像这样将真空语句移到末尾:

DO $$
BEGIN
  -- parent table
  FOR i IN 1..10000 LOOP
    INSERT INTO my_parent_table( ... ) VALUES ...;
  END LOOP;

  -- child table
  FOR i IN 1..50000 LOOP
    INSERT INTO my_child_table( ... ) VALUES ...;
  END LOOP;
END;
$$;

VACUUM ANALYZE my_parent_table;
VACUUM ANALYZE my_child_table;

这给了我同样的错误。有什么方法可以将真空分析合并到添加数据的同一脚本中?

我正在使用 PostgreSQL v 9.2。

【问题讨论】:

批量insert 之后就不需要真空了。仅当您删除或更新大量数据时才需要vacuum(因为它会回收不再需要的空间)。在您的情况下,analyze 本身就足够了。 谢谢,但我真的想要“真空分析”;在为所需的测试场景添加新数据之前,脚本首先删除所有现有数据。我已经编辑了这个问题以明确这一点。 如果您的脚本首先删除所有现有数据,也许您应该截断表,从而避免需要清理。 除了 jjanes 答案之外,在delete(或truncate)之后执行vacuum analyze before insert将是瞬间的。 This answer on dba.stackexchange 为我解决了这个问题:在您的函数中调用 ANALYZE,但将其留给 autovacuum 以优雅地释放空间(只需确保您已为您的大桌子)。 【参考方案1】:

如果您从 pgAdmin3 查询窗口中使用“执行查询”按钮运行此程序,则会将整个脚本作为一个字符串发送到服务器。

如果您从查询窗口的“执行 pgScript”按钮执行它,它会单独发送命令,因此会起作用,但它不容忍匿名块的 DO 语法。您必须创建一个执行当前匿名工作的函数,然后使用以下内容调用“执行 pgScript”:

select inserts_function();
VACUUM ANALYZE my_parent_table;
VACUUM ANALYZE my_child_table;

【讨论】:

pgAdmin4中没有“执行pgScript”按钮 pgAdmin4 那时还不存在。【参考方案2】:

我实施的最终解决方案是 a_horse_with_no_namexzilla 在 cmets 中提出的建议的综合:

使用 TRUNCATE 代替 DELETE 避免了对 VACUUM 的需要 ANALYZE 可以根据需要在脚本期间单独使用

【讨论】:

以上是关于VACUUM 不能从函数或多命令字符串执行的主要内容,如果未能解决你的问题,请参考以下文章

如何从使用 pg_cron 运行的清除例程中链接 VACUUM?

来自 SQLiteOpenHelper 的 VACUUM sqlite 数据库

Postgresql之VACUUM和VACUUM FULL对比

SQLite Vacuum

Codeforces 922DRobot Vacuum Cleaner

怎么解决SQLite数据库删除大数据后执行“VACUUM”效率低的有关问题