【发布时间】:2018-06-24 15:15:37
【问题描述】:
我无法理解查询计划缓存如何用于 pl/pgsql。
我想使用JOINs 和IFs 构建多合一查询,因此我将有多个不同的查询参数,并且我将在多个表中进行搜索。
一开始我以为使用pl/pgsql会为每个参数组合产生不同的方案,事实并非如此,因为我有不止一个表
直接出现在 PL/pgSQL 函数中的 SQL 命令必须引用 每次执行时都使用相同的表和列;也就是说,你不能 在 SQL 命令中使用参数作为表或列的名称。到 绕过这个限制,您可以使用构建动态命令 PL/pgSQL EXECUTE 语句——以执行新解析为代价 分析并在每次执行时构建新的执行计划。 from here
我猜每次执行新的分析都会减慢速度。如果我不使用EXECUTE 那么
如果语句没有参数,或者被执行多次,SPI 经理将考虑制定一个不依赖于 特定的参数值,并将其缓存以供重复使用。通常这 只有当执行计划对 其中引用的 PL/pgSQL 变量的值。如果是, 每次制定计划都是净赢。 from here
那么我应该使用通用计划吗?是更快,还是因为每次都没有计划而变慢?至少它们被缓存了。我的查询对它们的变量很敏感,因为它们是动态的,但是
如果是这样,每次制定一个计划就是一个净赢。
实际上是什么意思?每次使用EXECUTE/plan 比通用的好还是坏? “净赢”让我感到困惑。
如果一个通用计划不准确并且EXECUTE/planning 每次都比较慢,那么为什么还要使用 pl/pgsql?我可以用几个 if 写一个简单的查询。
底线是,我无法断定EXECUTE/plan each time 在速度和计划缓存方面是否优于generic cached plan。请解释和建议,我很困惑。
作为参考,这是我正在创建的。像现在一样工作,但会为mytables 和mywhere 添加更多的 IF
DROP FUNCTION IF EXISTS __aa(ii int, fk int);
CREATE FUNCTION __aa(ii int, fk int) RETURNS TABLE(id INTEGER,val text, fd integer) AS $$
DECLARE
myt text;
mytables text;
mywhere text;
BEGIN
mytables := 'dyn_tab2';
mywhere := 'dyn_tab2.id=$1';
IF fk IS NOT NULL
THEN
mywhere := mywhere || 'AND dyn_tab2.fk_id=$2';
END IF;
RETURN QUERY EXECUTE format('
SELECT dyn_tab2.id, dyn_tab2.value, dyn_tab2.fk_id
FROM %I WHERE ' ||mywhere,
mytables)
USING ii, fk;
END;
$$
LANGUAGE 'plpgsql';
谢谢
【问题讨论】:
标签: postgresql caching database-design plpgsql query-planner