作者
digoal
日期
2022-03-25
标签
PostgreSQL , 递归 , work table 记录数评估
以前递归查询的work table记录数是代码写死的, work table平均记录数评估为非递归字句记录数的10倍:
rel->tuples = 10 * cte_rows;
写死有个问题, 因为不同的递归场景, work_table的记录数实际上差异挺大.
- 对于递归的图式全展开(每一层都不设置limit)查询, 每一个work table可能是上一级的N倍, 例如每个人关联10个人, 那么第一层10条, 第二层可能100条, 第三层可能1000条.
- 对于最短路径查询每一层都limit 1条返回, 那么work table记录数就可以取初始记录的倍数为1.
PostgreSQL 15新增GUC recursive_worktable_factor (默认依旧是10), 倍数可以由用户自己控制.
https://www.postgresql.org/docs/devel/queries-with.html#QUERIES-WITH-RECURSIVE
https://www.postgresql.org/docs/devel/runtime-config-query.html#RUNTIME-CONFIG-QUERY-OTHER
recursive_worktable_factor (floating point)
Sets the planner's estimate of the average size of the working table of a recursive query,
as a multiple of the estimated size of the initial non-recursive term of the query.
This helps the planner choose the most appropriate method for joining the working table to the query's other tables.
The default value is 10.0.
A smaller value such as 1.0 can be helpful when the recursion has low “fan-out” from one step to the next,
as for example in shortest-path queries.
Graph analytics queries may benefit from larger-than-default values.
例子
WITH RECURSIVE t(n) AS (
VALUES (1) -- non-recursive term , 初始记录数
UNION ALL
SELECT n+1 FROM t WHERE n < 100 -- recursive query, 产出working table, 也就是要recursive_worktable_factor评估的平均每个working table的记录数.
)
SELECT sum(n) FROM t;
/*
* set_cte_size_estimates
* Set the size estimates for a base relation that is a CTE reference.
*
* The rel's targetlist and restrictinfo list must have been constructed
* already, and we need an estimate of the number of rows returned by the CTE
* (if a regular CTE) or the non-recursive term (if a self-reference).
*
* We set the same fields as set_baserel_size_estimates.
*/
void
set_cte_size_estimates(PlannerInfo *root, RelOptInfo *rel, double cte_rows)
{
RangeTblEntry *rte;
/* Should only be applied to base relations that are CTE references */
Assert(rel->relid > 0);
rte = planner_rt_fetch(rel->relid, root);
Assert(rte->rtekind == RTE_CTE);
if (rte->self_reference)
{
/*
* In a self-reference, we assume the average worktable size is a
* multiple of the nonrecursive term's size. The best multiplier will
* vary depending on query "fan-out", so make its value adjustable.
*/
rel->tuples = clamp_row_est(recursive_worktable_factor * cte_rows);
}
else
{
/* Otherwise just believe the CTE's rowcount estimate */
rel->tuples = cte_rows;
}
/* Now estimate number of output rows, etc */
set_baserel_size_estimates(root, rel);
}
递归用法参考:
《PostgreSQL 递归CTE 模拟一维空间的元胞自动机 - 复杂系统研究 自组织,涌现》
《PostgreSQL 递归查询 - 深度优先、广度优先 搜索举例 - BREADTH DEPTH》
《PostgreSQL 递归查询中不支持 order by, 聚合函数, 自包含子查询的》
《PostgreSQL 递归一例, 问题、回答、留言, 1对多对多的结构》
《森林状图式数据(树状) 的 高效生成方法》
《重新发现PostgreSQL之美 - 6 index链表跳跳糖 (CTE recursive 递归的详细用例)》
《PostgreSQL - 时序、IoT类场景 - first_value , last_value , agg , cte , window , recursive》
《PostgreSQL 14 preview - recovery 性能增强 - recovery_init_sync_method=syncfs - 解决表很多时, crash recovery 递归open所有file的性能问题 - 需Linux新内核支持》
《PostgreSQL 14 preview - SQL标准增强, 递归(CTE)图式搜索增加广度优先、深度优先语法, 循环语法 - breadth- or depth-first search orders and detect cycles》
《PostgreSQL 递归查询在分组合并中的用法》
《递归+排序字段加权 skip scan 解决 窗口查询多列分组去重的性能问题》
《PostgreSQL 排序去重limit查询优化 - 递归 vs group分组 (loop降到极限, block scan降到极限)》
《PostgreSQL 家族图谱、社交图谱、树状关系、藤状分佣、溯源、等场景实践 - 递归,with recursive query (有向无环 , 有向有环)》
《累加链条件过滤 - 递归、窗口、UDF、游标、模拟递归、scan 剪切》
《PostgreSQL 并行计算解说 之29 - parallel 递归查询, 树状查询, 异构查询, CTE, recursive CTE, connect by》
《PostgreSQL 递归应用实践 - 非“传销”的高并发实时藤、树状佣金分配体系》
《PostgreSQL 家谱、族谱类应用实践 - 图式关系存储与搜索》
《PostgreSQL 递归妙用案例 - 分组数据去重与打散》
《PostgreSQL Oracle 兼容性之 - INDEX SKIP SCAN (递归查询变态优化) 非驱动列索引扫描优化》
《PostgreSQL 图式搜索(graph search)实践 - 百亿级图谱,毫秒响应》
《PostgreSQL 实践 - 内容社区(如论坛)图式搜索应用》
《小微贷款、天使投资(风控助手)业务数据库设计(图式搜索\图谱分析) - 阿里云RDS PostgreSQL, HybridDB for PostgreSQL最佳实践》
《PostgrSQL 递归SQL的几个应用 - 极客与正常人的思维》
《PostgreSQL 递归查询CASE - 树型路径分组输出》
《用PostgreSQL找回618秒逝去的青春 - 递归收敛优化》
《distinct xx和count(distinct xx)的变态递归优化方法 - 索引收敛(skip scan)扫描》
《时序数据合并场景加速分析和实现 - 复合索引,窗口分组查询加速,变态递归加速》
《PostgreSQL雕虫小技cte 递归查询,分组TOP性能提升44倍》
《PostgreSQL 使用递归SQL 找出数据库对象之间的依赖关系 - 例如视图依赖》
《PostgreSQL 递归死循环案例及解法》
《PostgreSQL 递归查询一例 - 资金累加链》
《PostgreSQL Oracle 兼容性之 - WITH 递归 ( connect by )》
《递归优化CASE - group by & distinct tuning case : use WITH RECURSIVE and min() function》
《递归优化CASE - performance tuning case :use cursor\trigger\recursive replace (group by and order by) REDUCE needed blockes scan》
《PostgreSQL 树状数据存储与查询(非递归) - Use ltree extension deal tree-like data type》
期望 PostgreSQL 增加什么功能?
PolarDB for PostgreSQL云原生分布式开源数据库
PostgreSQL 解决方案集合
德哥 / digoal's github - 公益是一辈子的事.





