2016-12-30 3 views
1

У меня есть очень большой массив, который я вычислил с Apache Madlib, и я хотел бы применить операцию к каждому отдельному массиву в этом 2d массиве.Как быстро отключить массив 2d в массиве 1d в PostgreSQL?

Я нашел код, который может помочь мне отключить его от this related answer. Тем не менее, этот код очень медленный на этом действительно большом массиве 2d (массивы с плавающей запятой 150 000 + 1d). В то время как unnest() занимает всего несколько секунд, даже после ожидания нескольких минут код не завершился.

Несомненно, должен быть более быстрый способ отключить большой массив 2d на меньшие массивы 1d? Бонусная точка, если это решение использует Apache Madlib. Я нашел один вывод утопает в документации под названием deconstruct_2d_array, однако, когда я пытаюсь вызвать эту функцию на матрице, она не со следующей ошибкой:

ERROR: Function "deconstruct_2d_array(double precision[])": Invalid type conversion. Internal composite type has more elements than backend composite type.

ответ

2

Функция вы нашли в моем старом ответе не масштабируется хорошо для больших массивов. Я никогда не думал о массивах вашего размера, который, вероятно, должен быть набором (таблица).

Как бы то ни было, эта функция 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; 

40x быстрее в моем тесте на большом 2d-массиве в Postgres 9.6.

STRICT, чтобы избежать исключения для ввода NULL (как commented by IamIC):

ERROR: FOREACH expression must not be null

+0

Спасибо, @Erwin, очень полезно! Он просто должен быть отмечен как STRICT. – IamIC

+0

@IamIC: Спасибо, я добавил это. –

0

Существует в настоящее время встроенный 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 является индекс в 2D массив

Смежные вопросы