我在数据库后端使用 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
Run Code Online (Sandbox Code Playgroud)
我对 SQL 优化很陌生,我试图了解以下行为:
目前该isReportAdmin函数仅返回“true”
create or replace function isReportAdmin(employee_id integer) RETURNS bool AS $$
BEGIN
RETURN 't';
END;
$$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
当我运行报告查询时,大约需要两分钟来执行。
如果我简单地替换函数调用: CASE WHEN true THEN...
返回需要两秒钟。
你能解释一下,为什么函数调用会产生如此多的开销?在查询中处理此类函数是否有通用策略?
是的,PL/pgSQL 确实会产生性能开销。在大多数情况下,您可以通过将函数定义为language sql:
create or replace function isreportadmin(employee_id integer)
RETURNS bool
AS $$
select true;
$$
LANGUAGE sql
stable;
Run Code Online (Sandbox Code Playgroud)
如果它被定义为stablePostgres 通常能够内联(SQL)函数并完全摆脱开销。
很可能您的实际函数在数据库中进行了一些查找。您仍然可以将其保留为 SQL 函数。例如,如果您有一个名为的表user_roles,您需要在其中查找传递的员工 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;
Run Code Online (Sandbox Code Playgroud)