一个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)

相关推荐
NineData4 小时前
NineData 与统信服务器操作系统完成兼容认证
数据库·oracle·操作系统·软件·数据库管理工具·ninedata·统信
智慧物业老杨5 小时前
物业日常巡查的数智化重构:从“打卡式巡检“到“闭环式风控“
android·java·人工智能·系统架构·rxjava
开开心心就好9 小时前
批量提取PDF中的图片,直接导出原图
前端·javascript·支持向量机·智能手机·pdf·html·启发式算法
步行cgn12 小时前
Spring c 命名空间注入详解
java·后端·spring
明月_清风12 小时前
Maven 到底是什么?一篇文章搞懂 Java 项目构建与依赖管理
java·后端·maven
aramae12 小时前
MySQL复合查询(8)
java·c语言·开发语言·后端·算法
Rain的Java大神之路13 小时前
如何快速上传10G文件
java·spring boot·redis·后端·mysql·spring cloud·面试
十二同学啊13 小时前
向量数据库:从核心原理到 RAG 与 Java 实战
数据库
默_笙13 小时前
🏛 给 AI 配一间办公室:Harness Engineering 六大模块与它的实现
前端·javascript
Wang's Blog13 小时前
Java 接入Redis: 通用命令与键管理
java·服务器·redis