基本上我想将查询结果分配给自定义类型属性。但是我注意到直接从 PostgreSQL 控制台查询大约是 0.071 毫秒,在函数内部是 0.400 毫秒和几次调用后的 0.170 毫秒。explain analyze
甚至在第一种情况下显示索引的使用,但在第二种情况下不显示。
这就是我正在做的事情。
CREATE OR REPLACE FUNCTION fun_isliked(
par_client client.id%type,
par_feed feed.id%type
)
RETURNS boolean
AS
$$
BEGIN
RETURN (
EXISTS(
SELECT
1
FROM
feedlike fl
WHERE
fl.client = par_client
AND fl.feed = par_feed
AND fl.state = 1
)
);
END;
$$ LANGUAGE plpgsql STABLE;
以下是explain analyze
上述两种情况的输出:
postgres=# explain analyze select exists (select 1 from feedlike where client = 13 and feed = 68 and state = 1);
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------
Result (cost=8.30..8.31 rows=1 width=0) (actual time=0.037..0.037 rows=1 loops=1)
InitPlan 1 (returns $0)
-> Index Scan using feedlike_client_feed_unique on feedlike (cost=0.28..8.30 rows=1 width=0) (actual time=0.034..0.034 rows=1 loops=1)
Index Cond: ((client = 13) AND (feed = 68))
Filter: (state = 1)
Total runtime: 0.086 ms
postgres=# explain analyze select * from fun_isliked(13, 68);
QUERY PLAN
----------------------------------------------------------------------------------------------------------
Function Scan on fun_isliked (cost=0.25..0.26 rows=1 width=1) (actual time=0.398..0.398 rows=1 loops=1)
Total runtime: 0.416 ms
为了在函数内有效地获得相同的运行时,有什么可能的解决方法?甚至可能吗?另外,我正在运行 PostgreSQL 9.3。
我发现SO 中的这个问题有我需要的东西,但是在我尝试了所选答案中的所有内容并且在减少运行时间方面没有成功之后,我决定提出一个新问题。
房间里的大象是头顶的功能。当调用函数而不是原始 SQL 时,Postgres 需要在系统目录中查找函数(可能会在函数重载的情况下选择最佳匹配)并考虑函数的设置。然后是函数调用本身的开销。这增加了很小的间接成本。
这仅对于像您的示例这样的非常简单的查询才真正重要-应该使用普通的 SQL 函数来实现。您仍然会遇到使用 SQL 函数的一些(微小)函数开销,但如果它很简单并且满足某些先决条件,则可以“内联”它
SELECT
。像往常一样,重复调用会从填充的缓存中获益。对于 plpgsql 函数,它也可能在一些(通常是 5 次)调用后开始使用通用计划,如果这看起来很有希望的话。
考虑一下关于 pgsql-general 的相关讨论。
plpgsql 函数中代码的查询计划
你想知道:
plpgsql 函数是查询计划器的黑匣子,它不检查函数的内容。它们充当优化障碍。与 SQL 函数不同,它们的内容不能内联到外部查询中。
这就是为什么
EXPLAIN ANALYZE
不显示plpgsql 函数内部发生的事情的原因,因此您看不到索引扫描。索引(很可能)仍在使用。您可以使用附加模块auto_explain
查看函数内 SQL 代码的查询计划。详细考虑这个相关问题的答案: