【问题标题】:How to unnest a 2d array into a 1d array quickly in PostgreSQL?如何在 PostgreSQL 中快速将 2d 数组取消嵌套到 1d 数组中?
【发布时间】:2017-05-15 02:50:43
【问题描述】:

我有一个用 Apache Madlib 计算的非常大的数组,我想对该二维数组中的每个单个数组应用一个操作。

我找到了可以帮助我从this related answer 中取消嵌套它的代码。但是,在这个非常大的 2d 数组(150,000+ 1d 浮点数组)上,代码非常慢。虽然unnest() 只需要几秒钟的运行时间,但即使等待了几分钟,代码也没有完成。

当然,必须有一种更快的方法将大型二维数组分解为更小的一维数组?如果该解决方案使用 Apache Madlib,则可以加分。我确实在名为 deconstruct_2d_array 的文档中找到了一条线索,但是,当我尝试在矩阵上调用该函数时,它失败并出现以下错误:

错误:函数“deconstruct_2d_array(双精度[])”:无效 类型转换。内部复合类型的元素多于 后端复合类型。

【问题讨论】:

    标签: sql arrays performance postgresql madlib


    【解决方案1】:

    您在我的旧答案中找到的函数不适用于大型数组。我从没想过你的数组大小,应该是一个集合(一个表)。

    尽管如此,这个 plpgsql 函数替换了referenced answer 中的函数。需要 Postgres 9.1 或更高版本。

    CREATE OR REPLACE FUNCTION unnest_2d_1d(ANYARRAY, OUT a ANYARRAY)
      RETURNS SETOF ANYARRAY AS
    $func$
    BEGIN
       FOREACH a SLICE 1 IN ARRAY $1 LOOP
          RETURN NEXT;
       END LOOP;
    END
    $func$  LANGUAGE plpgsql IMMUTABLE STRICT;
    

    在我在 Postgres 9.6 中对大型二维数组进行的测试中,速度提高了 40 倍。

    STRICT 避免 NULL 输入异常(如commented by IamIC):

    错误:FOREACH 表达式不能为空

    【讨论】:

    • 谢谢@Erwin,非常有用!只需将其标记为 STRICT。
    • @IamIC:谢谢,我补充了。
    【解决方案2】:

    现在有一个内置的 MADlib 函数来执行此操作 - array_unnest_2d_to_1d,它是在 1.11 版本中引入的: http://madlib.incubator.apache.org/docs/latest/array__ops_8sql__in.html#af057b589f2a2cb1095caa99feaeb3d70

    这是一个示例用法:

    CREATE TABLE test1 (pid int, points double precision[]);
    INSERT INTO test1 VALUES
    (100,  '{{1.0, 2.0, 3.0}, {4.0, 5.0, 6.0}, {7.0, 8.0, 9.0}}'),
    (101,  '{{11.0, 12.0, 13.0}, {14.0, 15.0, 16.0}, {17.0, 18.0, 19.0}}'),
    (102,  '{{21.0, 22.0, 23.0}, {24.0, 25.0, 26.0}, {27.0, 28.0, 29.0}}');
    SELECT * FROM test1;
    

    生产

     pid |               points               
    -----+------------------------------------
     100 | {{1,2,3},{4,5,6},{7,8,9}}
     101 | {{11,12,13},{14,15,16},{17,18,19}}
     102 | {{21,22,23},{24,25,26},{27,28,29}}
    (3 rows)
    

    然后调用unnest函数:

    SELECT pid, (madlib.array_unnest_2d_to_1d(points)).* 
    FROM test1 ORDER BY pid, unnest_row_id;
    

    生产

    pid | unnest_row_id | unnest_result 
    -----+---------------+---------------
     100 |             1 | {1,2,3}
     100 |             2 | {4,5,6}
     100 |             3 | {7,8,9}
     101 |             1 | {11,12,13}
     101 |             2 | {14,15,16}
     101 |             3 | {17,18,19}
     102 |             1 | {21,22,23}
     102 |             2 | {24,25,26}
     102 |             3 | {27,28,29}
    (9 rows)
    

    其中 unnest_row_id 是二维数组的索引

    【讨论】:

    • 您好,在 UBUNTU 中安装 madlib 有简单的方法吗?
    猜你喜欢
    • 2022-01-13
    • 2021-12-05
    • 1970-01-01
    • 2019-07-23
    • 1970-01-01
    • 1970-01-01
    • 2021-10-12
    • 1970-01-01
    • 2021-09-18
    相关资源
    最近更新 更多