Greenplum 函数内嵌套查询在query中调用的替代方案

本文涉及的产品
云原生数据库 PolarDB 分布式版,标准版 2核8GB
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介: 背景 在使用数据库过程中,用户可能会封装一些函数,用来返回一些映射值。 例如,有一张表存储了学号和学生名字,写一个函数,根据学号,返回学生名字。 SQL如下 : create table tab(id int primary key, std_name name); cr

背景

在使用数据库过程中,用户可能会封装一些函数,用来返回一些映射值。

例如,有一张表存储了学号和学生名字,写一个函数,根据学号,返回学生名字。

screenshot

SQL如下 :

create table tab(id int primary key, std_name name);

create or replace function f1(int) returns name as 
$$

  select std_name from tab where id=$1;

$$
 language sql strict volatile;

dwh=> insert into tab values (1,'abc');
INSERT 0 1

dwh=> select f1(1);
 f1  
-----
 abc
(1 row)
AI 代码解读

使用Greenplum时,可能需要注意,因为如果函数中有QUERY,但是这个函数又在QUERY中调用的话,可能会报错。

目前执行计划还不支持这种查询:

dwh=> select f1(id) from tab;
ERROR:  XX000: function cannot execute on segment because it accesses relation "public.tab" (functions.c:155)  (seg0 slice1 e45f16674.cloud.nu17:3017 pid=20659) (cdbdisp.c:1326)
DETAIL:  SQL function "f1" during startup
LOCATION:  cdbdisp_finishCommand, cdbdisp.c:1326
AI 代码解读

出错原因,在检查segment节点query tree时,如果发现树中还有非catalog类的对象,则报错。
可能是master节点对这种QUERY的处理没有彻底。

/**
 * Walker for querytree_safe_for_segment.
 */
bool querytree_safe_for_segment_walker(Node *expr, void *context)
{
        Assert(context == NULL);

        if (!expr)
        {
                /**
                 * Do not end recursion just because we have reached one leaf node.
                 */
                return false;
        }

        switch(nodeTag(expr))
        {
                case T_Query:
                        {
                                Query *q = (Query *) expr;

                                if (!allow_segment_DML &&
                                        (q->commandType != CMD_SELECT
                                         || q->intoClause != NULL
                                         || q->resultRelation > 0))
                                {
                                        elog(ERROR, "function cannot execute on segment because it issues a non-SELECT statement");
                                }

                                ListCell * f = NULL;
                                foreach(f,q->rtable)
                                {
                                        RangeTblEntry *rte = (RangeTblEntry *) lfirst(f);

                                        if (rte->rtekind == RTE_RELATION)
                                        {
                                                Assert(rte->relid != InvalidOid);

                                                Oid namespaceId = get_rel_namespace(rte->relid);

                                                Assert(namespaceId != InvalidOid);

                                                if (!(IsSystemNamespace(namespaceId) ||
                                                          IsToastNamespace(namespaceId) ||
                                                          IsAoSegmentNamespace(namespaceId)))
                                                {
                                                        elog(ERROR, "function cannot execute on segment because it accesses relation \"%s.%s\"",
                                                                        quote_identifier(get_namespace_name(namespaceId)), quote_identifier(get_rel_name(rte->relid)));
                                                }
                                        }
                                }
                                query_tree_walker(q, querytree_safe_for_segment_walker, context, 0);  
...
AI 代码解读

使用with也不能解决这个问题,因为不会等收到master节点后再调用f1

dwh=> with t as (select * from tab) select f1(id) from t;
ERROR:  XX000: function cannot execute on segment because it accesses relation "public.tab" (functions.c:155)  (seg0 slice1 e45f16674.cloud.nu17:3017 pid=26324) (cdbdisp.c:1326)
DETAIL:  SQL function "f1" during startup
LOCATION:  cdbdisp_finishCommand, cdbdisp.c:1326

dwh=> with t as (select * from tab) select * from t;
 id | std_name 
----+----------
  1 | abc
  2 | abc
(2 rows)

聚合后还是不行
dwh=> with t as (select array_agg(id) ag from tab) select unnest(ag) from t;
 unnest 
--------
      2
      1
(2 rows)

dwh=> with t as (select array_agg(id) ag from tab) select f1(unnest(ag)) from t;
ERROR:  XX000: query plan with multiple segworker groups is not supported (cdbdisp.c:302)
HINT:  likely caused by a function that reads or modifies data in a distributed table
CONTEXT:  SQL function "f1" statement 1
LOCATION:  cdbdisp_dispatchToGang, cdbdisp.c:302
AI 代码解读

怎么解决这个问题呢?
可以用子查询(括号中的部分)替代 function 。

dwh=> select *, (select std_name from tab where tab.id=t.id) from tab t;
 id | std_name | ?column? 
----+----------+----------
  1 | abc      | abc
(1 row)
AI 代码解读
目录
打赏
0
0
0
1
20702
分享
相关文章
Greenplum【SQL 03】实现树结构+自定义函数+避免函数重复调用+ function cannot execute on a QE slice 问题处理(优化过程全记录)
Greenplum【SQL 03】实现树结构+自定义函数+避免函数重复调用+ function cannot execute on a QE slice 问题处理(优化过程全记录)
255 0
IOC控制反转&&DI依赖注入的方法论
控制反转(IoC)是面向对象编程中用于减少代码耦合的设计原则。传统编程中,对象通过`new`关键字创建,控制权在应用手中。而在Spring框架下,对象由IoC容器管理并创建,通过依赖注入(DI)机制,自动将所需资源注入对象中,从而实现对象间的解耦。DI有两种实现方式:构造方法注入和属性setter方法注入。通过IoC和DI,程序更易于维护和测试。
236 0
DNS缓存中毒原理
【8月更文挑战第17天】
251 1
强化学习在复杂环境中的应用与挑战
【8月更文第9天】强化学习(Reinforcement Learning, RL)是一种机器学习方法,通过智能体与环境的交互来学习最优策略。近年来,随着计算能力的提升和算法的进步,强化学习被广泛应用于各种复杂环境下的任务,如机器人导航、游戏策略优化等。本文将探讨强化学习在这些领域中的应用案例,并分析所面临的挑战及其潜在的解决方案。
790 4
Paimon 实践 | 基于 Flink SQL 和 Paimon 构建流式湖仓新方案
Paimon 实践 | 基于 Flink SQL 和 Paimon 构建流式湖仓新方案
4342 59
Spring Cloud Alibaba Sentinel 整合 nacos 进行规则持久化
Spring Cloud Alibaba Sentinel 整合 nacos 进行规则持久化
3242 0
Spring Cloud Alibaba Sentinel 整合 nacos 进行规则持久化
技术写作概述:内容分析、平台和转化追踪以及内容老化
内容分析是一种技术作家用来解释和量化文本数据的研究方法。它涉及从不同来源的文本中编码和识别主题或模式的系统过程,这些来源包括书籍、博客、文章或其他文档类型。其主要目标是提供主观解释的、但有效且可重复的、从数据中得出的推论。这种技术有助于确定所讨论的内容是否有效地传达了所需的交流,或者是否存在需要改进的领域。例如,您可以进行内容分析来衡量软件手册的用户友好性或教学指南的清晰性和易懂性。
176 0
SpringCloud Alibaba系列(三) Sentinel黑白名单限制
  很多时候,我们需要根据调用来源来判断该次请求是否允许放行,这时候可以使用 Sentinel 的来源访问控制(黑白名单控制)的功能。来源访问控制根据资源的请求来源(origin)限制资源是否通过,若配置白名单则只有请求来源位于白名单内时才可通过;若配置黑名单则请求来源位于黑名单时不通过,其余的请求通过。
407 0
5、DataX(DataX简介、DataX架构原理、DataX部署、使用、同步MySQL数据到HDFS、同步HDFS数据到MySQL)(一)
5、DataX(DataX简介、DataX架构原理、DataX部署、使用、同步MySQL数据到HDFS、同步HDFS数据到MySQL)(一)
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等