UDF и большие cstring параметры

Запросы, планы, оптимизация запросов, ...

Модераторы: kdv, CyberMax

Ответить
marcodor
Сообщения: 9
Зарегистрирован: 09 мар 2010, 23:49

UDF и большие cstring параметры

Сообщение marcodor » 10 мар 2010, 15:16

Добрый день!

Есть 2-3 удфки которые обрабатывают стринг-массивы, типа 1.2.3.4., например
DECLARE EXTERNAL FUNCTION ARRAYLEFT CSTRING(200), CSTRING(1), INTEGER RETURNS CSTRING(200) FREE_IT ENTRY_POINT 'ArrayLeft' MODULE_NAME 'warrays';
Замечал что если параметры большие, то очень сильно влияют на производительность. Например если длина 200 то запрос выполнялся в среднем за 800мс если 1000 то за 3с 600мс на тех же данных, железе.
Сам код удф-ок оптимизирован на максиме, данные в обеях случаех те же. Подозреваю что тормоза в менеджере памяти, тоесть на выделение по 1000байт на каждую запись. Хотя, возврат например той же функции я выделяю память через ib_malloc из удфки, и я аллокирую реальную длина строки, а не 1000 каждый раз. в 90% он не доходит до 200 символов, но хочется какбы страховатся потому что теоретически длинны могут быть больше.

Кстати по резултатам этим удфок идет групировка, тоесть например

select
arrayleft(C.CHILD_ROOTS, '.', 2), D.KIND,
sum(D.Dt) as Dt,
sum(D.Ct) as Ct
from TS_FORMDET D
join TS_ACCOUNT_CHILD C on (C.CHILD_ID = D.ACCOUNT_ID)
where (C.ACCOUNT_ID = 1) and (D.FDATE BETWEEN '1900-01-01' AND '2009-12-31')
group by 1, 2


На 2.5 есть заметное ускоренее, но всеже.
Вот и возникли некоторые вопросы/замыслы.
Все входные параметры CSTRING в принципе могут быть и без длинны, зачем их лимитировать? В дллке они же попадают как PChar, так пусть передают только поинтер к начале стрига и все, не так ли?
Результат функции как-бы должен быть лимитирован в длинну, чтоб движок знал сколько зарезервировать под каждую запись, но возникает вопрос, как же встроенный substring работает, сколько выделяет, вижу

select substring('aaaaaa' from 2 for 1) from RDB$DATABASE
union all
select substring('aaaaaaaaaaaaaaaaaaa' from 3 for 6) from RDB$DATABASE

обрабатывает без проблем.

Или попытатся как блоб их отправить/получать, но подозреваю это будет изващенство.

Хотелось бы услышать Ваши советы.

hvlad
Разработчик Firebird
Сообщения: 1244
Зарегистрирован: 21 мар 2005, 10:48

Re: UDF и большие cstring параметры

Сообщение hvlad » 10 мар 2010, 16:16

Тормоза живут в аллокаторе, по крайней мере часть их.
При каждом выполнении UDF
а) выделяется память для всех вх. пар-ров
б) выделяется память под возврат. значения FREE_IT
в) освобождается память для всех вх. пар-ров
г) освобождается память для возврат. значения

Для (а), если памяти нужно немного, то она выделяется в стеке - это максимально быстро. В 2.5 из стека берётся до 800 байт (не спрашивайте, почему именно столько). Соотв. твоя строка в 1000 байт уже выделяется аллокатором движка, это медленнее.

До 2.5 (б) и (г) делала CRT (malloc), в 2.5 это делается с помощью пулов движка, отсюда ускорение.

По идее, (б) и (г) можно вообще избежать, если использовать механизм RETURNS PARAMETER N

marcodor
Сообщения: 9
Зарегистрирован: 09 мар 2010, 23:49

Re: UDF и большие cstring параметры

Сообщение marcodor » 10 мар 2010, 18:41

Влад, спасибо за внятный ответ!

С RETURN PARAMETER есть прирост ~15%. В принципе это меня устраивает, не такие уж тормознутые эти удфки ;)
Сам запрос, даже без них тяжеловатый, сервер наверное шустрее надо будет ставить.

-
D.

Ответить