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

相关推荐
小bo波9 小时前
Java Swing 图形用户界面实验 —— 从算术练习到游戏开发的完整实践
java·课程设计·gui·游戏开发·扫雷·swing
万少11 小时前
万少的博客 - 技术分享与解决方案
前端·javascript·后端
咖啡八杯11 小时前
GoF设计模式——备忘录模式
java·后端·spring·设计模式
尘世中一位迷途小书童13 小时前
用 Cesium 撸了一个森林火情监控大屏,弧线、粒子、发光效果都齐了
前端·javascript
先吃饱再说14 小时前
存储的进化:从 MySQL 到浏览器缓存,数据到底住在哪?
数据库
Nturmoils15 小时前
字段太多看不全,ksql 的展开模式和输出控制怎么用
数据库·后端
先吃饱再说15 小时前
JavaScript中`this` 的“千层套路”:从默认绑定到箭头函数的五种指向
javascript
foxire15 小时前
基于nodejs实现服务端内核引擎
javascript
Databend17 小时前
Agent 轨迹分析与归因的数据工程实践
大数据·数据库·agent
触底反弹17 小时前
🧠 搞懂 Token,才算真正入门大模型——从分词原理到 Embedding 语义实战
javascript·人工智能·算法