Greenplum使用存储过程报错function cannot execute on a QE slice because it accesses relation
报错信息:
在Greenplum数据库中,我们使用存储过程查询数据的时候会报错如下信息
function cannot execute on a QE slice because it accesses relation
首先我们先了解下复制表
复制表(Replicated Table)
Greenplum 6支持一种新的分布策略:复制表,即整张表在每个节点上都有一个完整的拷贝。
test=# CREATE TABLE t2 (id int) DISTRIBUTED REPLICATED; CREATE TABLE test=# INSERT INTO t2 VALUES (1), (2), (3); INSERT 0 3 test=# SELECT * FROM t2; id ---- 1 2 3 (3 rows) test=# SELECT gp_segment_id, * from t2; gp_segment_id | id ---------------+---- 0 | 1 0 | 2 0 | 3
UDF 在 segment 上不能访问任何表。由于 MPP 的特性,任何 segment 仅仅包含部分数据,因而在 segment 执行的 UDF 不能访问任何表,否则数据计算错误。
yydzero=# CREATE FUNCTION c() RETURNS bigint AS $$ yydzero$# SELECT count(*) from t1 AS result; yydzero$# $$ LANGUAGE SQL; CREATE FUNCTION yydzero=# SELECT c(); c --- 6 (1 row) yydzero=# select c() from t2; ERROR: function cannot execute on a QE slice because it accesses relation "public.t1" (seg0 slice1 192.168.1.107:25435 pid=76589)
如果把上面的t1改成复制表,则不存在这个问题。
避免分布式查询计划:
如果一张表的数据在各个segment上都有拷贝,那么就可以生成本地连接计划,而避免数据在集群的不同节点间移动。如果用复制表存储数据量比较小的表(譬如数千行),那么性能有明显的提升。 数据量大的表不适合使用复制表模式。
解决方案
找到了原因,就简单了,只需要修改建表语句即可解决问题
ALTER TABLE table_name SET DISTRIBUTED REPLICATED;
参考文档