如何在视图的上下文中提高使用递归CTE的函数的性能?

时间:2018-12-12 18:06:14

标签: postgresql

我有一个函数,该函数采用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。 / p>

在理想状态下,我将能够执行主查询视图,然后仅在主查询结果中存在manager_hierarchy的情况下调用organization_id,最后添加相关的层次结构信息到视图的每一行。我似乎无法想到一种在视图上下文中完成此特定工作流的方法。我考虑过但想避免的其他想法是,创建一个物化视图来存储所有组织的层次结构信息,或者使用临时表来记录manager_hierarchy的结果。

如何最好地改善此视图的性能?

0 个答案:

没有答案