在数据库后端中使用Postgres 9.3的报表中有以下相当简单的查询:
SELECT * FROM source
JOIN sourcelevel USING (source_id)
JOIN level USING (level_id)
WHERE
CASE WHEN isReportAdmin(1) THEN true
ELSE source_id in (SELECT source_id FROM sourceemployee WHERE employee = 1)
END
我对SQL优化非常陌生,并且试图了解以下行为:
目前isReportAdmin
函数仅返回“ true”
create or replace function isReportAdmin(employee_id integer) RETURNS bool AS $$
BEGIN
RETURN 't';
END;
$$ LANGUAGE plpgsql;
运行报表查询时,大约需要两分钟的时间来执行。
如果我将函数调用简单地替换为:CASE WHEN true THEN...
需要两秒钟才能返回。
您能否用中间术语来解释,为什么函数调用会产生如此多的开销?在查询中是否存在处理此类功能的通用策略?
答案 0 :(得分:3)
是的,PL / pgSQL确实产生了performance overhead。在大多数情况下,您可以通过将函数定义为language sql
来消除开销:
create or replace function isreportadmin(employee_id integer)
RETURNS bool
AS $$
select true;
$$
LANGUAGE sql
stable;
如果将其定义为stable
,Postgres通常可以使用inline(SQL)函数并完全摆脱开销。
您的实际函数很可能在数据库中进行了一些查找。您仍然可以将其保留为SQL函数。如果您例如有一个名为user_roles
的表,您需要在其中查找所传递的employee_id,您可以使用类似以下的内容:
create or replace function isreportadmin(p_employee_id integer)
RETURNS bool
AS $$
select exists (select *
from user_roles ur
where ur.employee_id = p_employee_id
and ur.is_admin);
$$
LANGUAGE sql
stable;