У меня есть функция, которая принимает массив organization_ids
и затем рекурсивно перечисляет деревья иерархии сотрудников этих организаций.Он параметризован organization_ids
, поэтому вызывающие функции могут запрашивать только ту информацию, которая им нужна, поскольку непараметрическое рекурсивное представление будет слишком дорогим для использования.
Функция довольно проста и выглядитнапример:
create or replace function manager_hierarchy (variadic organization_ids int[])
returns table(organization_id int, employee_id int, managers_above_ids int[]) as $$
with recursive filtered_manager_assignments as (
select a.manager_id, a.employee_id
from manager_assignments a
inner join employees e on e.id = a.employee_id and e.organization_id in (select unnest(organization_ids))
where a.effective_date_range @> current_date
),
hierarchy(organization_id, employee_id, managers_above_ids) as (
select e.organization_id, e.id, array[]::integer[]
from employees e
where e.organization_id in (select unnest(organization_ids))
and e.id not in (select employee_id from filtered_manager_assignments)
union all
select h.organization_id, a.employee_id, array_append(h.managers_above_ids, a.manager_id)
from hierarchy h
inner join filtered_manager_assignments a on a.manager_id = h.employee_id
)
select * from hierarchy;
$$ LANGUAGE SQL STABLE COST 100000;
Сама функция довольно производительна, но у меня возникают трудности при разработке стратегии для ее эффективного применения в контексте представления.Определение представления, в которое я его встраиваю, довольно сложное, но простой пример должен также проиллюстрировать мою трудность:
create view v_employees (
select e.organization_id, concat(e.first_name, ' ', e.last_name) name, h.managers_above_ids
from employees e
inner join manager_hierarchy(e.organization_id) h on h.employee_id = e.id
);
Это представление будет чрезвычайно медленным для запроса, так как manager_hierarchy
функция вызывается для каждой строки представления.Я мог бы сохранить результаты вызова функции в CTE, но это исключает использование аргумента organization_ids
функции manager_hierarchy
для извлечения только того, что необходимо.Например, если пользователь представления выполняет select * from v_employees where organization_id = 1
, я не знаю, как мне известно в контексте CTE, вызывать manager_hierarchy
с единственным аргументом 1
.
InВ идеальном состоянии я мог бы выполнить представление основного запроса, а затем вызвать manager_hierarchy
только с organization_id
, присутствующими в результате основного запроса, прежде чем, наконец, добавить соответствующую информацию иерархии в каждую строку представления.Кажется, я не могу придумать способ выполнить этот конкретный рабочий процесс в контексте представления.Другие идеи, которые я рассмотрел, но хотел бы избежать, - это создание материализованного представления для хранения информации об иерархии для всех организаций или запоминание результатов manager_hierarchy
с использованием временной таблицы.
Как лучше всего поступитьулучшить производительность этого представления?