【问题标题】:Query plan caching with pl/pgsql使用 pl/pgsql 进行查询计划缓存
【发布时间】: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。请解释和建议,我很困惑。

作为参考,这是我正在创建的。像现在一样工作,但会为mytablesmywhere 添加更多的 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


    【解决方案1】:

    静态查询计划(没有EXECUTE)总是被缓存,动态查询计划(EXECUTE)不能被缓存。

    在您的情况下,无论如何都无法使用静态查询,因为正如您所引用的,这意味着您只能在查询中使用一组固定的表。

    我了解到您对文档中关于静态和动态查询之间权衡的讨论感到困惑。

    定义:查询参数是不属于查询字符串的值,例如$1 或静态查询中的 PL/pgSQL 变量名。

    对于静态查询,过程如下:

    对于前 5 次执行,将使用实际参数值(“自定义计划”)进行计划,并且如果估计的执行时间不明显短于忽略实际参数值的计划(“通用计划”) ”),通用计划将从第六次执行开始使用。

    由于通用计划被缓存,这意味着从第六次执行开始没有计划成本。

    动态查询在每次执行时都有计划。

    权衡如下:动态查询在执行时会增加计划成本,但由于始终使用实际参数值进行计划,因此最终会得到更好的执行计划,这可以节省查询执行期间的时间.

    现在如果一个查询对参数值敏感,这意味着最优计划会随着参数值的变化而显着变化,所以如果你每次都计划查询通常你会赢。

    没有参数的查询总是会从计划缓存中受益,除非表内容在单个会话的生命周期内发生很大变化,从而导致缓存计划变得次优。

    【讨论】:

    • 感谢您的详细解答。这解释了很多,是的,我很困惑“在文档中讨论静态和动态查询之间的权衡”。 Here 表示使用动态 sql 会为每个参数组合获取单独的查询计划。我想没有办法在 pl/pgsql 中得到它?
    • 另外,你在哪里找到有关查询计划的详细信息,我正在搜索 Chitij Chauhan 的 PostgreSQL Cookbook ISBN 978-1-78355-533-8 和 Simon Riggs Hannu Krosing 的 PostgreSQL 9 Administration Cookbook ISBN 978-1-849510-28-8,我没有发现有关计划和 pl/pgsql 的任何信息。再次感谢。
    • 在这里谈论 PL/pgSQL。动态查询是使用EXECUTE 语句运行的查询。我没有读过你引用的书,但来源有所有的信息,每个人都可以阅读。关注邮件列表也是获取知识的好方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多