UDF и большие cstring параметры
Добавлено: 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
обрабатывает без проблем.
Или попытатся как блоб их отправить/получать, но подозреваю это будет изващенство.
Хотелось бы услышать Ваши советы.
Есть 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
обрабатывает без проблем.
Или попытатся как блоб их отправить/получать, но подозреваю это будет изващенство.
Хотелось бы услышать Ваши советы.