greenplum中的递归查询

Posted

技术标签:

【中文标题】greenplum中的递归查询【英文标题】:Recursive query in greenplum 【发布时间】:2015-01-13 07:42:06 【问题描述】:

我需要在 greenplum MPP 的子/父表中创建一个面包屑字段

原始表有2个字段:父亲,孩子 我需要用面包屑提取视图

例如有这个记录

1, 2
1, 3
2, 4
4, 5

我需要提取:

1/2
1/3
1/2/4 
1/2/4/5

等等

Greenplum 是一个基于 postgresql 8.2 的 MPP 处理引擎。基本上它是一个postgres 但是,给定版本,它不支持 8.3 中的“带有递归”的 postgresql 功能。

此外,如果我尝试创建一个函数来完成这项工作,我会遇到其他 GP 限制

例如,如果我创建如下函数


    CREATE OR REPLACE FUNCTION   getBreadCrumb(decimal) RETURNS text AS 'DECLARE
    itemid ALIAS FOR $1;
    itemfullname text;
    itemrecord RECORD;
    BEGIN
        SELECT * INTO itemrecord FROM mytable where father=itemid;
        itemfullname := coalesce(itemfullname, '''') || itemrecord.father::text;
        IF itemrecord.child IS NOT NULL  THEN
           itemfullname := itemfullname || ''/'' || getBreadCrumb(itemrecord.child)::text ;
           RETURN itemfullname;
        ELSE
           RETURN itemfullname;
        END IF;
    END'  LANGUAGE 'plpgsql'

然后尝试从中选择我得到的


    ERROR:  function cannot execute on segment because it accesses relation "mytable" (functions.c:152)

在我看来,这与 greenplum 的“无共享”架构有关。

还有其他想法来创建面包屑以提供我所拥有的环境吗?

提前致谢

【问题讨论】:

【参考方案1】:

我在处理层次结构时遇到了类似的问题。解决这个问题的唯一选择是编写一个在 master 上执行的 pl/pgsql 函数,它会像这样在循环中更新“层次结构”字段:

初始内容:

Node_id | Parent_id | Hierarchy
1       | null      | 1
2       | 1         | 2
3       | 1         | 3
4       | 3         | 4
5       | 3         | 5
6       | 5         | 6

第一次迭代:

Node_id | Parent_id | Hierarchy
1       | null      | 1
2       | 1         | 2, 1
3       | 1         | 3, 1
4       | 3         | 4, 3
5       | 3         | 5, 3
6       | 5         | 6, 5

第二次迭代:

Node_id | Parent_id | Hierarchy
1       | null      | 1
2       | 1         | 2, 1
3       | 1         | 3, 1
4       | 3         | 4, 3, 1
5       | 3         | 5, 3, 1
6       | 5         | 6, 5, 3

最后一次迭代:

Node_id | Parent_id | Hierarchy
1       | null      | 1
2       | 1         | 2, 1
3       | 1         | 3, 1
4       | 3         | 4, 3, 1
5       | 3         | 5, 3, 1
6       | 5         | 6, 5, 3, 1

您可以进行的一项优化以避免在每次迭代中完全自联接是存储额外的“级别”字段并为更新的记录增加它(因为只有在迭代时更新的记录 i 应该考虑在迭代时更新i+1)

很遗憾,GPDB 不支持with recursive 和在段级别执行查询,所以这是唯一的选择

【讨论】:

我想到了一个类似的解决方案,但在我的情况下,层次结构的深度是未知的。只是为了让其他人知道,我将此逻辑转移到了 oracle 原始数据库,我从中提取了数据,并添加了一个带有层次结构的计算字段 如果不知道深度,则必须进行很多循环。但在我的情况下,即使有 500m 行具有 100 个层次结构的表,它也能正常工作

以上是关于greenplum中的递归查询的主要内容,如果未能解决你的问题,请参考以下文章

oracle 递归 通过子节点查询根节点

详解SQL中的递归问题

检索递归 SQL 查询中的特定级别

DB for z/OS 中的递归查询

RedShift 中的递归查询

锚和递归查询“CTE”列“ColumnName”中的递归部分之间的类型不匹配