Присоединяйтесь к процедурам только один раз в Firebird

Я пытаюсь соединить две хранимые процедуры в запросе Firebird. В моем примере данные первый возвращает 70 записей, второй только 1 запись.

select
    --...
from MYSP1('ABC', 123) s1
    left join MYSP2('DEF', 456) s2
         on s1.FIELDA = s2.FIELDA
        and s1.FIELDB = s2.FIELDB

Проблема в производительности: это занимает 10 секунд, а каждая процедура занимает меньше 1 секунды. Я подозреваю, что процедуры выполняются несколько раз, а не один раз. Имеет смысл выполнить их только один раз, потому что я передаю им фиксированные параметры.

Есть ли способ заставить Firebird просто выполнять каждую процедуру один раз, а затем объединять их результаты?


person bluish    schedule 03.10.2017    source источник
comment
Насколько я знаю, нет, хотя вы можете попытаться объединить два подвыбора из этих хранимых процедур. Однако нет времени проверить, действительно ли это работает.   -  person Mark Rotteveel    schedule 03.10.2017
comment
@MarkRotteveel, спасибо, я попробовал ваше предложение, но оно не улучшает производительность.   -  person bluish    schedule 03.10.2017
comment
Тогда я боюсь, что нет пути; присоединение к хранимой процедуре ведет себя как боковое соединение (оно оценивается для каждой строки в управляющей «таблице»).   -  person Mark Rotteveel    schedule 03.10.2017
comment
являются ли эти FIELDA и FIELDB произвольными сгенерированными данными или они являются подмножеством, взятым из какой-то таблицы словаря?   -  person Arioch 'The    schedule 10.10.2017
comment
@Arioch'Это всего лишь примеры полей, возвращенных из SP. Имена произвольны.   -  person bluish    schedule 10.10.2017
comment
Печальный. В противном случае вы можете соединить оба SP с таблицей исходного словаря.   -  person Arioch 'The    schedule 10.10.2017
comment
А может вы меня неправильно поняли? Я спросил об источнике значений, а не об именах столбцов   -  person Arioch 'The    schedule 10.10.2017
comment
@Arioch'Хорошо :) теперь я понял ... данные из SP произвольные, словарной таблицы нет ... все равно спасибо   -  person bluish    schedule 11.10.2017


Ответы (2)


Поскольку кажется, что это невозможно, я решил эту проблему, запустив этот запрос внутри новой хранимой процедуры, где я кэширую все результаты из MYSP2 в глобальную временную таблицу и выполняю соединение между MYSP1 и временной таблицей.

Это временное определение таблицы:

create global temporary table MY_TEMP_TABLE
(
    FIELDA varchar(3) not null,
    FIELDB smallint not null,
    FIELDC varchar(10) not null
 );

Это тело хранимой процедуры:

--cache MYSP2 results
delete from MY_TEMP_TABLE;
insert into MY_TEMP_TABLE
    select *
    from MYSP2('DEF', 456)
    ;

--join data
for
select
    --...
from MYSP1('ABC', 123) s1
    left join MY_TEMP_TABLE s2
         on s1.FIELDA = s2.FIELDA
        and s1.FIELDB = s2.FIELDB
into
    --...
do
    suspend;

Но если есть другое решение без временных таблиц, было бы здорово!

person bluish    schedule 03.10.2017
comment
Честно говоря, я бы заполнил таблицу результатами обоих SP (используя MERGE), а затем выбрал бы из GTT для вывода. Таким образом, вы сможете обойтись без постоянного SP (первая часть отправляется как EXECUTE BLOCK), если это необходимо. Кроме того, укажите, что GTT рассчитывается для каждой транзакции, а не для каждого соединения. - person Arioch 'The; 10.10.2017

Может быть, это может помочь:

with MYSP2W as (MYSP2('DEF', 456))
select
    --...
from MYSP1('ABC', 123) s1
    left join MYSP2W s2
    on s1.FIELDA = s2.FIELDA
    and s1.FIELDB = s2.FIELDB
person Daniel Vidić    schedule 03.10.2017
comment
спасибо, но этот запрос не может быть запущен. Во всяком случае, я попытался использовать предложение WITH для включения одной из процедур, но ничего не изменилось. - person bluish; 04.10.2017