Как я могу улучшить производительность функции, которая использует рекурсивный CTE в контексте представления? - PullRequest
0 голосов
/ 12 декабря 2018

У меня есть функция, которая принимает массив 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 с использованием временной таблицы.

Как лучше всего поступитьулучшить производительность этого представления?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...