【问题标题】:Postgresql slow array assignmentPostgresql 慢速数组赋值
【发布时间】:2015-12-18 13:27:20
【问题描述】:

我正在使用 postgresql 中的存储过程/函数。我有一个名为 sports 的表,并且我有一个 sports%ROWTYPE 数组:

records = "sports"[10000];

我还有一个循环(10 000 次迭代),在其中创建一条记录并将其分配给记录数组:

for idx in ....
loop
   record.x = something;
   record.y = something_else

   records[idx] = record;
end loop;

由于某种原因,语句 records[idx] = record; 需要 20 多秒才能执行(对于 10 000 次迭代)。

我不知道为什么这个作业要花这么长时间。

编辑

我有一个带有 3 个参数的存储过程

x text;
y integer[][];
z integer[];

我的目标是将这些数据存储在如下表中:

x | y[0]  | z[0]
x | y[1]  | z[1]
x | y[..] | z[..]
x | y[n]  | z[n]

【问题讨论】:

  • 我也试过了:records = array_append(records, record); 但大约需要 15 秒
  • 为什么要创建数组而不是临时表? PostgreSQL 是一个 dbms,而不是一个“ams”。如果您将数据存储在临时表中,那么事情可能会比存储在数组中快得多。 PostgreSQL 甚至原生支持事务本地临时表,因此将其存储在表中非常容易。最后,您的解释带有 XY 问题的味道。请解释您要达到的目标;这样你就更有可能得到满意的答案。
  • 我添加了更多信息
  • 如果可以,请尝试使用 PG 9.5 alpha 的代码并测量差异。您的案例看起来像 commit 1dc5ebc9 所要解决的问题。

标签: arrays performance postgresql function stored-procedures


【解决方案1】:

PostgreSQL 通常不会就地修改数组。当您修改一个时,它会被复制以制作新的。

您应该避免尝试迭代地构建或修改数组。而是使用集合。在这种情况下,我会定义一个函数来构建一条记录,然后用array_agg 调用它来创建数组,比如

select array_agg(r)
from generate_series(1,10000) i,
     my_function(whatever_input_you_need)
into records;

如果您可以通过使用 ROW(...) 构造函数而不定义函数而逃脱,那就更好了,例如:

select array_agg(ROW(col1, col2, col3))
from generate_series(1,10000) i,
     my_function(whatever_input_you_need);

Daniel Vérté noted that this has changed for arrays modified in plpgsql in PostgreSQL 9.5,所以它应该更有效率。在 9.5 上,您的代码可能运行良好,并且看到差异会很有趣。

【讨论】:

  • 我实际上尝试了该解决方案。它下降到4秒。它好多了,但我需要更快的东西。我会试试 ROW 解决方案
  • @benjamin.d 拆分成独立函数的次数越少越好。理想的做法是在一个查询中完成。
猜你喜欢
  • 1970-01-01
  • 2012-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-10
  • 1970-01-01
  • 2016-01-17
相关资源
最近更新 更多