我很难理解查询计划缓存如何为pl / pgsql工作。
我想用JOIN
和IF
构建一体化查询,因此我将拥有多个不同的查询参数,并且我将搜索更多的一个表。< / p>
起初我以为使用pl / pgsql会为每个参数组合产生不同的计划,但事实并非如此,因为我有多个表
直接出现在PL / pgSQL函数中的SQL命令必须引用 每次执行都有相同的表和列;也就是说,你做不到 使用参数作为SQL命令中表或列的名称。至 绕过这个限制,你可以使用构造动态命令 PL / pgSQL EXECUTE语句 - 以执行新解析的代价 分析并构建每次执行的新执行计划。 from here
每次进行新的分析都会减慢我的想法。如果我不使用EXECUTE
那么
如果语句没有参数,或者多次执行,则SPI 经理将考虑创建一个不依赖的通用计划 特定参数值,并缓存重复使用。通常这个 只有在执行计划对此不敏感时才会发生 其中引用的PL / pgSQL变量的值。如果是, 每次制定计划都是净胜利。 from here
我应该使用通用计划吗?它更快,还是更慢,因为每次都没有计划?至少它们是缓存的。我的查询对它们的变量很敏感,因为它们是动态的,但是
如果是这样,每次产生一个计划都是净胜利。
实际上意味着什么?每次使用EXECUTE
/计划,比通用的更好还是更差? &#34;净胜利&#34;困惑我。
如果通用计划不准确并且EXECUTE
/计划每次都较慢,那么为什么还要使用pl / pgsql?我可以用几个ifs编写一个简单的查询。
根据速度和计划缓存,我无法断定EXECUTE/plan each time
在generic cached plan
方面是否优于mytables
。请解释和建议,我很困惑。
作为参考,这就是我正在创造的。现在可以正常工作,但会为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';
php artisan --version
由于
答案 0 :(得分:10)
静态查询计划(不包含EXECUTE
)始终被缓存,动态查询计划(EXECUTE
)无法缓存。
在您的情况下,无论如何都不可能使用静态查询,因为正如您所引用的那样,这意味着您只能在查询中使用一组固定的表。
我认为你对文档中静态和动态查询之间的权衡讨论感到困惑。
定义:查询参数是不属于查询字符串的值,如$1
或静态查询中的PL / pgSQL变量名。
对于静态查询,过程如下:
对于前5次执行,将使用实际参数值(“自定义计划”)计划,并且如果估计的执行时间不会明显短于忽略实际参数值的计划的执行时间(“通用计划” “),通用计划将从第六次执行中使用。
由于通用计划已缓存,这意味着第六次执行时没有计划成本。
每次执行时都会计划动态查询。
权衡如下:动态查询在执行时会计划成本,但由于它们总是按实际参数值进行规划,因此最终会得到更好的执行计划,这可以节省查询执行期间的时间
现在,如果查询对参数值敏感,则表示最佳计划会随参数值而显着变化,因此如果您每次都计划查询,通常会获胜。
没有参数的查询将始终从计划缓存中获益,除非表内容在单个会话的生命周期中发生很大变化,因此缓存的计划变得不是最理想的。