powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / хочу странного. пятничный псто про аггрегирование строк в LOOP
9 сообщений из 9, страница 1 из 1
хочу странного. пятничный псто про аггрегирование строк в LOOP
    #38999196
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А есть ли способ из plpgsql кода вызвать
Код: sql
1.
2.
3.
string_agg_transfn(internal, text, text);
--и
string_agg_finalfn(internal)


скажем в LOOP [и, вторую, -- после] .
если да -- то как [,карл] ?


а то в loop может быть весьма навороченная логика, с трудом превращающаяся в динамич. SQL -- а, как показывает тест, string_agg существенно выигрывает у
Код: src
1.
2.
3.
LOOP
 var:=var||chunk;
 .....
END LOOP;


когда chunk небольшие, а результат под 3 ляма символов.

запрос нынче праздный (удалось таки всю логику запихать в string_agg )
но на будущее.


1. и вообще -- не грозятся ли byRef когда нибудь в plpgsql изобразить
и кто как выкручивается, если выкручивается. когда надо шить длинные строки[скрипты] из данных
может быть в других pl ?


2.да, и правильно ли я понимаю, что concat("any") | concat_ws(text, "any"); не спасёт -- т.к. проблема в самой передаче "по значению", а от неё мы уйти не можем ? или неправильно ?
...
Рейтинг: 0 / 0
хочу странного. пятничный псто про аггрегирование строк в LOOP
    #38999252
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwwq,

Если меня память не подводит проблема в том что var:=var||chunk; каждый раз делает новую строку и получается куча palloc/pfree очень дорогих. (тоже самое с созданием ARRAY путем последовательного добавления элементов).

Я бы посоветовал просто навороченную логику в отдельную хранимку загнать а далее вызывать через select string_agg(...) into something from _sp(arguments). Скорее всего самый эффективный метод.

--
Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
хочу странного. пятничный псто про аггрегирование строк в LOOP
    #38999266
Фотография vyegorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim BogukЕсли меня память не подводит проблема в том что var:=var||chunk; каждый раз делает новую строку и получается куча palloc/pfree очень дорогих. (тоже самое с созданием ARRAY путем последовательного добавления элементов).
В 9.5 Том поправил это.
...
Рейтинг: 0 / 0
хочу странного. пятничный псто про аггрегирование строк в LOOP
    #38999275
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Bogukqwwq,

Если меня память не подводит проблема в том что var:=var||chunk; каждый раз делает новую строку и получается куча palloc/pfree очень дорогих. (тоже самое с созданием ARRAY путем последовательного добавления элементов).
Maxim BogukЯ бы посоветовал просто навороченную логику в отдельную хранимку загнать а далее вызывать через select string_agg(...) into something from _sp(arguments). Скорее всего самый эффективный метод.
принимается.
в эту сторону я не подумал.


PS
иллюстрация к исходной постановке
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
EXPLAIN (ANALYZE on, VERBOSE off, COSTS on, BUFFERS on, TIMING on )
SELECT string_agg(concat(i,i,i,i,i,i,i,i,i,i)::text,'')  FROM generate_series(1,100000) g(i)
;
---------------------
"Aggregate  (cost=15.00..15.01 rows=1 width=4) (actual time=1523.726..1523.728 rows=1 loops=1)"
"  Buffers: temp read=172 written=171"
"  ->  Function Scan on generate_series g  (cost=0.00..10.00 rows=1000 width=4) (actual time=15.877..788.150 rows=100000 loops=1)"
"        Buffers: temp read=172 written=171"
"Planning time: 0.044 ms"
"Execution time: 1529.662 ms"



Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
CREATE OR REPLACE FUNCTION loop_agg ()
	RETURNS text as
$body$
DECLARE
	var text:='';
BEGIN
	FOR i IN 1..100000
	LOOP
		var:=var || concat(i,i,i,i,i,i,i,i,i,i)::text;
	END LOOP;
	RETURN var;
END;
$body$
language plpgsql;
EXPLAIN ANALYZE SELECT loop_agg ();
--------------------
"Result  (cost=0.00..0.26 rows=1 width=0) (actual time=312814.533..312814.885 rows=1 loops=1)"
"Planning time: 0.034 ms"
"Execution time: 312814.944 ms"
...
Рейтинг: 0 / 0
хочу странного. пятничный псто про аггрегирование строк в LOOP
    #38999278
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwwqMaxim Bogukqwwq,

Если меня память не подводит проблема в том что var:=var||chunk; каждый раз делает новую строку и получается куча palloc/pfree очень дорогих. (тоже самое с созданием ARRAY путем последовательного добавления элементов).
Maxim BogukЯ бы посоветовал просто навороченную логику в отдельную хранимку загнать а далее вызывать через select string_agg(...) into something from _sp(arguments). Скорее всего самый эффективный метод.
принимается.
в эту сторону я не подумал.


PS
иллюстрация к исходной постановке
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
EXPLAIN (ANALYZE on, VERBOSE off, COSTS on, BUFFERS on, TIMING on )
SELECT string_agg(concat(i,i,i,i,i,i,i,i,i,i)::text,'')  FROM generate_series(1,100000) g(i)
;
---------------------
"Aggregate  (cost=15.00..15.01 rows=1 width=4) (actual time=1523.726..1523.728 rows=1 loops=1)"
"  Buffers: temp read=172 written=171"
"  ->  Function Scan on generate_series g  (cost=0.00..10.00 rows=1000 width=4) (actual time=15.877..788.150 rows=100000 loops=1)"
"        Buffers: temp read=172 written=171"
"Planning time: 0.044 ms"
"Execution time: 1529.662 ms"



Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
CREATE OR REPLACE FUNCTION loop_agg ()
	RETURNS text as
$body$
DECLARE
	var text:='';
BEGIN
	FOR i IN 1..100000
	LOOP
		var:=var || concat(i,i,i,i,i,i,i,i,i,i)::text;
	END LOOP;
	RETURN var;
END;
$body$
language plpgsql;
EXPLAIN ANALYZE SELECT loop_agg ();
--------------------
"Result  (cost=0.00..0.26 rows=1 width=0) (actual time=312814.533..312814.885 rows=1 loops=1)"
"Planning time: 0.034 ms"
"Execution time: 312814.944 ms"





-- "поправил"
...
Рейтинг: 0 / 0
хочу странного. пятничный псто про аггрегирование строк в LOOP
    #38999287
p2.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если проблема в перекопировании всего накапливаемого объема при каждой конкатенации - можно конкатенировать ограниченный объем и сохранять в массив, а потом конвертировать в результирующую строку. Кстати, обратить внимание на тип. Возможно plpgsql по разному управляет памятью для varchar(1000) и varchar(1e6) или text, а может быть и фиксированный char(...).
Диагностировать проблему перекопирования можно заметив нелинейное увеличение времени с ростом результирующей строки.

Затык может быть еще и в обычно употребляемой кодировке utf8. Варианты функций для работы с символами переменной длины значительно уступают фиксированным по скорости. И производительность некоторых падает с ростом строки.
...
Рейтинг: 0 / 0
хочу странного. пятничный псто про аггрегирование строк в LOOP
    #38999306
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
p2.Если проблема в перекопировании всего накапливаемого объема при каждой конкатенации - можно конкатенировать ограниченный объем и сохранять в массив, а потом конвертировать в результирующую строку.
массив конкатенируется так же. если не использовать array_agg, котрый работает аналогично string_agg

-- вероятно копит array|строку по ссылке в "internal" и возвращает по последнему вызову финальной функции
...
Рейтинг: 0 / 0
хочу странного. пятничный псто про аггрегирование строк в LOOP
    #38999326
p2.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwwqмассив конкатенируется так жеимел ввиду array_to_string. глупо было бы внутри такой функции заниматься переливанием из пустополного в биткомпорожнее.
...
Рейтинг: 0 / 0
хочу странного. пятничный псто про аггрегирование строк в LOOP
    #39000237
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
p2.qwwqмассив конкатенируется так жеимел ввиду array_to_string. глупо было бы внутри такой функции заниматься переливанием из пустополного в биткомпорожнее.и что ? массив то надо сконкатенировать.

выигрыш тут в числах

при N выделений памяти ~1..N затраты ~C0* n*N/2

если N ~ M*K то сшивка:
оценкаC 0 *m*M/2 {строки длиной m}
+ C 0 *k*K/2{итого}
+ C 1 *k*N/2{сшивка массива, длиной k, строк длиной m/2}


вот если бы хранить результат промежуточных сшивок без этих затрат (на конкатенацию массива C 1 ...) -- то можно бы попарно сливать на каждой итерации. (наверное через set returning можно. вроде бы сеты быстро размещаются).
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / хочу странного. пятничный псто про аггрегирование строк в LOOP
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]