sle*_*vin 4 postgresql database-design caching plpgsql query-planner
我很难理解查询计划缓存如何为pl/pgsql工作.
我想用JOINs和IFs 构建一体化查询,所以我将有多个不同的查询参数,我将在更多的一个表中搜索.
起初我以为使用pl/pgsql会为每个参数组合产生不同的计划,但事实并非如此,因为我有多个表
直接出现在PL/pgSQL函数中的SQL命令必须在每次执行时引用相同的表和列; 也就是说,您不能将参数用作SQL命令中表或列的名称.要解决此限制,您可以使用PL/pgSQL EXECUTE语句构造动态命令 - 代价是执行新的解析分析并在每次执行时构建新的执行计划. 从这里
每次执行一次新的分析都会减慢我的想法.如果我不使用EXECUTE那么
如果语句没有参数,或者多次执行,则SPI管理器将考虑创建一个不依赖于特定参数值的通用计划,并缓存该计划以供重用.通常,仅当执行计划对其中引用的PL/pgSQL变量的值不是非常敏感时才会发生这种情况.如果是这样,每次产生一个计划都是净胜利.从这里
我应该使用通用计划吗?它更快,还是更慢,因为每次都没有计划?至少它们是缓存的.我的查询对它们的变量很敏感,因为它们是动态的,但是什么
如果是这样,每次产生一个计划都是净胜利.
实际意味着?EXECUTE每次使用/计划,比通用的更好还是更差?"净胜利"让我困惑.
如果通用计划不准确和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';
Run Code Online (Sandbox Code Playgroud)
谢谢
Lau*_*lbe 10
静态查询(无EXECUTE)的计划始终被缓存,动态查询(with EXECUTE)的计划无法缓存.
在您的情况下,无论如何都不可能使用静态查询,因为,正如您引用的那样,这意味着您只能在查询中使用一组固定的表.
我收集到您对文档中静态和动态查询之间的权衡讨论感到困惑.
定义:查询参数是不属于查询字符串的值,如$1静态查询中的PL/pgSQL变量名称.
对于静态查询,过程如下:
对于前5次执行,将使用实际参数值("自定义计划")进行计划,如果估计的执行时间不会明显短于忽略实际参数值的计划("通用计划"),通用计划将从第六次执行中使用.
由于通用计划被缓存,这意味着第六次执行没有计划成本.
每次执行时都会计划动态查询.
权衡如下:动态查询在执行时会计算成本,但由于它们总是按实际参数值进行规划,因此最终会得到更好的执行计划,这可以节省查询执行期间的时间.
现在,如果查询对参数值敏感,则意味着最佳计划将随参数值显着变化,因此如果您每次都计划查询,通常会获胜.
没有参数的查询将始终从计划缓存中获益,除非表内容在单个会话的生命周期中发生很大变化,因此缓存的计划变得不是最理想的.
| 归档时间: |
|
| 查看次数: |
1276 次 |
| 最近记录: |