一个KADB报错分析及实验

想把UDF的返回结果保存在表里面,结果执行报错:

test=# insert into footest select * from f5();

ERROR: function cannot execute on a QE slice because it accesses relation "public.foo" (entry db 192.168.85.133:5432 pid=4212)

CONTEXT: SQL statement "select * from (select * from foo where fooid<5 limit 100)a"

PL/pgSQL function f5() line 3 at RETURN QUERY

函数定义:

原始定义:

test=# CREATE OR REPLACE FUNCTION f5() RETURNS SETOF foo AS

test-# BODY

test$# BEGIN

test$# RETURN query select * from foo;

test$# END;

test# BODY$

test-# LANGUAGE plpgsql;

修改为:

CREATE OR REPLACE FUNCTION f5(out fooid int,out foosubid int,out fooname text) RETURNS SETOF record AS

BODY

declare

row record;

BEGIN

for row in select * from foo where foo.fooid<5 loop

fooid:=row.fooid;

foosubid:=row.foosubid;

fooname:=row.fooname;

return next;

end loop;

return;

END;

BODY

LANGUAGE plpgsql;

根据高通的一个issue:

https://knowledge.broadcom.com/external/article/296772/why-we-got-error-like-function-cannot-ex.html

报错原因:

Greenplum is an MPP database, under such architecture, in most cases, the master (AKA: QD, Query Dispatcher) will dispatch the job to the segments (AKA: Query Executor), then gather the result from QE at the end.
one of the limitations of such architecture is, we can not execute non-SELECT statement queries on QE

An example use case that may trigger such error is like below:
the user would like to collect the AO compaction info based on the list inside a table.

复制代码
gpadmin=# select oid,gp_toolkit.__gp_aovisimap_compaction_info(oid) from oid_list ;
ERROR:  function cannot execute on a QE slice because it issues a non-SELECT statement  (seg0 slice1 192.168.6.198:20000 pid=100663)

That is because:

  • the user table "oid_list" was distributed across all the segments

  • the query plan will first indentify the segmentID of target row of table "oid_list", the run the UDF __gp_aovisimap_compaction_info() on it

  • In this UDF there is an "EXECUTE" command inside it, Since EXECUTE is a non-select query, it can not run on QE, so get such error.

实验:

源表和目标表都必须为复制分布

目标表:

test=# create table footest(a text);

源表:

CREATE TABLE foo (fooid INT, foosubid INT, fooname TEXT);

INSERT INTO foo VALUES (1, 2, 'three');

INSERT INTO foo VALUES (4, 5, 'six');

保留数据:

test=# insert into footest select distinct(f5) from (select f5() from gp_dist_random('foo'))a;

INSERT 0 2

test=# select * from footest;

a


(1,2,three)

(4,5,six)

相关推荐
Flynt1 小时前
OpenJDK禁AI代码半年了,现在执行得怎么样?答案是:全靠自觉
java·开源·ai编程
这个DBA有点耶6 小时前
2026年分布式数据库有哪些主流选择?先评估这5个维度再决定
数据库·分布式·dba
古法安卓6 小时前
Android-日志系统源码解析
android·java·android studio
专业抄代码选手6 小时前
08|Fiber 上的 `useState`:状态终于属于具体组件
前端·javascript·react.js
默_笙6 小时前
😭 Vibe Coding 翻车实录:AI 编程为什么必须先写"剧本"
前端·javascript
lerhxx7 小时前
我用 R3F 手搓了一个能走进去的 3D 迷宫简历(上):从选型架构到迷宫生成算法
前端·javascript·three.js
小夏coding7 小时前
从"一把梭"到"精妙拆解" —— 滑动窗口计时框架的设计演进
java·后端
这个DBA有点耶8 小时前
从MySQL 5.7到8.0:JSON查询性能差在哪?虚拟列索引vs多值索引怎么选
数据库·mysql·架构
胡写代码8 小时前
数据库审计字段,别再每张表各写一套了——我统一成这 6 个字段
数据库
MacroZheng8 小时前
同事问我:"Claude Code经常失忆,不怕它把项目搞炸?",我:"怕,三个Markdown文件给它装个永不丢失的外置大脑!"
java·人工智能·后端