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

相关推荐
希望永不加班6 小时前
SpringBoot 接口签名验证(AppKey/Secret)
java·spring boot·后端·spring
阿正呀7 小时前
CSS粘性定位不生效怎么办_检查父元素高度与overflow属性设置
jvm·数据库·python
2403_883261097 小时前
如何获取DDL语句_DBMS_METADATA.GET_DDL提取对象定义
jvm·数据库·python
m0_613856297 小时前
mysql数据库乱码如何解决_mysql字符集与校对规则配置方法
jvm·数据库·python
我是Superman丶7 小时前
Antigravity Retry 自动重试脚本
前端·javascript·vue.js
Bert.Cai7 小时前
MySQL CEIL()函数详解
数据库·mysql
fengxin_rou7 小时前
RabbitMQ安装教程:windows本地安装和docker部署
java·分布式·后端·rabbitmq
a8a3027 小时前
Laravel7.x核心特性全解析
java·spring boot·后端
m0_602857767 小时前
Chart.js 4 中实现基于数据极值的垂直线性渐变填充
jvm·数据库·python
夏恪7 小时前
如何计算SQL同比环比数据_利用窗口函数LAG与LEAD
jvm·数据库·python