首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >含有gp_dist_random的函数在 Greenplum 中计算结果错误问题

含有gp_dist_random的函数在 Greenplum 中计算结果错误问题

作者头像
AiDBA宝典
发布2026-03-26 14:22:38
发布2026-03-26 14:22:38
200
举报

现象

如下SQL的运行结果是错误的:

代码语言:javascript
复制
SELECT
  n.nspname as schema_name,
  c.gp_segment_id,
  pg_size_pretty(SUM(pg_total_relation_size(c.oid))) as segment_size
FROM
  gp_dist_random ('pg_class') c
JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE
  c.relkind ='r'
AND n.nspname NOTIN ('pg_catalog', 'information_schema', 'gp_toolkit')
AND n.nspname !~'^pg_%'
GROUPBY
  n.nspname,
  c.gp_segment_id
ORDERBY n.nspname,gp_segment_id;

其实,应该是segment_id为0的占用了900MB。 下面的才是正确的:

QQ_1756780039480
QQ_1756780039480

QQ_1756780039480

直连segment 0 ,获取大小:

代码语言:javascript
复制
[root@mdw /]# PGOPTIONS='-c gp_session_role=utility' psql -h sdw1 -p 6000-U gpadmin -d db2
psql (13.12, server 12.12)
Type "help" for help.

db2=# \dt+ ods.*
                                      List of relations
 Schema |             Name             | Type  |  Owner  | Persistence |  Size  | Description 
--------+------------------------------+-------+---------+-------------+--------+-------------
 ods    | dds_imp_settle_pbt_rept_bt_d |table| gpadmin | permanent   |747 MB |
 ods    | dom_dept                     |table| gpadmin | permanent   |192 kB | 科信息
 ods    | dom_dept_rep                 |table| gpadmin | permanent   |32 kB  |
(3rows)

db2=# \di+ ods.*
                                                          List of relations
 Schema |                 Name                 | Type  |  Owner  |            Table             | Persistence |  Size  | Description 
--------+--------------------------------------+-------+---------+------------------------------+-------------+--------+-------------
 ods    | idx_dds_imp_settle_pbt_rept_bt_d_all | index | gpadmin | dds_imp_settle_pbt_rept_bt_d | permanent   |146 MB |
(1row)

db2=# 

分析

gp_dist_random()Greenplum Database 里的一个特殊系统函数,主要用于在 所有 segment 节点 上分布式地执行查询,返回每个 segment 上的结果集。这个函数有如下的作用:

  • • 在 Greenplum 中,数据是分布式存储的,不同的 segment 存储不同的数据。
  • gp_dist_random('表名') 的作用就是从 所有 segment 的本地表 中取数据,而不是像普通 SQL 那样通过协调器合并后的逻辑视图。
  • • 它会返回带有一个隐藏列 gp_segment_id 的结果,可以用来分析数据在各个 segment 上的分布情况。

这个SQL出错的问题在于:不能先做join操作,也不能先做group by、sum等聚合操作

代码语言:javascript
复制
SELECT
  n.nspname as schema_name,
  c.gp_segment_id,
  pg_size_pretty(SUM(pg_total_relation_size(c.oid))) as segment_size
FROM
  gp_dist_random ('pg_class') c
JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE
  c.relkind ='r'
AND n.nspname NOTIN ('pg_catalog', 'information_schema', 'gp_toolkit')
AND n.nspname !~'^pg_%'
GROUPBY
  n.nspname,
  c.gp_segment_id
ORDERBY n.nspname,gp_segment_id;

所以,修改为如下的结果是正确的:

代码语言:javascript
复制
SELECT schema_name,gp_segment_id,pg_size_pretty(sum(sz)) seg_size from (
    SELECT
      (select n.nspname from pg_namespace n where c.relnamespace = n.oid) as schema_name,
      c.relnamespace,
      c.gp_segment_id,
      pg_size_pretty((pg_total_relation_size (c.oid))) as segment_size,
      (pg_total_relation_size (c.oid))  sz
    FROM
      gp_dist_random ('pg_class') c
    WHERE
      c.relkind ='r' ) v 
WHERE v.schema_name NOTIN ('information_schema','gp_toolkit','pg_catalog','test','tmp')
      AND v.schema_name NOTLIKE'pg_temp%'
      GROUPBY schema_name,gp_segment_id
ORDERBY1,2;

总结

1、当有gp_dist_random函数时,不能先做join操作,也不能先做group by、sum等聚合操作,否则会导致数据不准确,可能是优化器只在某个执行器进程(QE)上计算,然后再把结果重分发,导致计算错误。

参考

https://groups.google.com/a/greenplum.org/g/gpdb-dev/c/DkTx4O-kuH0

https://www.enterprisedb.com/blog/how-do-postgresql-securitybarrier-views-work

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-09-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AIDB 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 现象
  • 分析
  • 总结
  • 参考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档