我无法理解查询计划缓存如何用于 pl/pgsql。
我想用JOIN
s 和IF
s 构建多合一查询,因此我将有多个不同的查询参数,并且我将在多个表中进行搜索。
起初我以为使用pl/pgsql会为每个参数组合产生不同的计划,事实并非如此,因为我有不止一个表
直接出现在 PL/pgSQL 函数中的 SQL 命令必须在每次执行时引用相同的表和列;也就是说,您不能将参数用作 SQL 命令中的表或列的名称。为了绕过这个限制,您可以使用 PL/pgSQL EXECUTE 语句构造动态命令——代价是执行新的解析分析并在每次执行时构造一个新的执行计划。 从这里
我猜每次执行新的分析都会减慢速度。如果我不使用EXECUTE
then
如果语句没有参数,或者执行了很多次,SPI 管理器将考虑创建一个不依赖于特定参数值的通用计划,并将其缓存以供重复使用。通常,只有当执行计划对其中引用的 PL/pgSQL 变量的值不是很敏感时,才会发生这种情况。如果是这样,那么每次制定计划都是一种净赢。从这里
那我应该使用通用计划吗?是更快,还是因为每次都没有计划而变慢?至少它们被缓存了。我的查询对它们的变量很敏感,因为它们是动态的,但是什么
如果是这样,那么每次制定计划都是一种净赢。
实际上是什么意思?EXECUTE
每次使用/plan 比通用的好还是坏?“净赢”让我感到困惑。
如果一个通用计划不准确并且EXECUTE
/planning 每次都比较慢,那么为什么还要使用 pl/pgsql 呢?然后我可以用几个 if 编写一个简单的查询。
底线是,我无法断定在速度和计划缓存方面EXECUTE/plan each time
是更好还是最差generic cached plan
。请解释和建议,我很困惑。
作为参考,这就是我正在创建的。像现在一样工作,但将添加更多的 IFmytables
和mywhere
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';
谢谢