GaussDB:根据relfilenode查找Schema、表名,判断是表文件还是索引文件

举报
骑着蚂蚁追大象 发表于 2021/12/17 10:54:48 2021/12/17
【摘要】 当我们已知GaussDB A集群某个数据节点的一个relfilenode,想知道其对应数据库的Schema、表名。

场景:

当我们已知GaussDB A集群某个数据节点的一个relfilenode,想知道其对应数据库的Schema、表名

情况分类:

1、relfilenode对应表文件,且表非分区

2、relfilenode对应索引文件,且索引对应表非分区

3、relfilenode对应表文件,且表分区

4、relfilenode对应索引文件,且索引对应表分区


案例:

1、创建非分区表lhk及设置主键;创建分区表lhk_p及创建索引

create table public.lhk
(
a int primary key,
b text
);

create table lhk.lhk_p
(
    a varchar(20),
    b text
)
partition by range(a)
(
    partition p_start values less than('2021-01-01'),
    partition p_202101 values less than('2021-02-01'),
    partition p_202102 values less than('2021-03-01'),
    partition p_202103 values less than('2021-04-01'),
    partition p_end values less than(MAXVALUE)
);

create index idx_lhk_p on lhk_p(a) local;


2、创建自定义函数public.pg_relfilenode_find(relfilenode integer, node_name name)

自定义函数输出:Schema、表名、relfilenode对应分区表/索引名字、文件路径、备注

CREATE OR REPLACE FUNCTION public.pg_relfilenode_find(relfilenode integer, node_name name)
 RETURNS TABLE(pg_namespace_nspname name, pg_class_relname name, pg_partition_relname name, filepath text, mark text)
 LANGUAGE plpgsql
 NOT FENCED
AS $$                                                                      
DECLARE  
  row_name1 record;  
  row_name2 record; 
  judge_str1 text;
  judge_str2 text;
    query_str1 text;
    query_str2 text; 
    query_str3 text; 
    query_str4 text;
    p1 text := 'Table and NO Partition';  --表文件且非分区表
    p2 text := 'Table and Partition';         --表文件且分区表
    p3 text := 'Index and Table NO partition'; --索引文件且非分区表的
    p4 text := 'Index and Table Partition';        --索引文件且分区表的
                                              
    BEGIN                     
               
        judge_str1 := 'EXECUTE DIRECT ON ('|| node_name ||')''select relkind, parttype from pg_class where relfilenode = '||relfilenode||';''';                                             
        --raise notice 'query_str1 is:% ',query_str1;
        FOR row_name1 IN EXECUTE(judge_str1) LOOP
          --表,单表
          IF row_name1.relkind <> 'i' AND row_name1.parttype = 'n' THEN
            
            query_str1 := 'EXECUTE DIRECT ON ('|| node_name ||')''select n.nspname, c.relname, cast(''''/'''' as name), cast(pg_relation_filepath('|| relfilenode ||') as text), cast('''''|| p1 ||''''' as text) from pg_class c, pg_namespace n where c.relnamespace = n.oid and c.relfilenode = '|| relfilenode ||';''';
            
            raise notice 'query_str1 is:% ',query_str1;

                  RETURN QUERY EXECUTE (query_str1);  
                  
                END IF; 
                
                --单表索引
          IF row_name1.relkind = 'i' THEN
            
            query_str3 := 'EXECUTE DIRECT ON ('|| node_name ||')''select n.nspname, c2.relname, cast(''''/'''' as name), cast(pg_relation_filepath('|| relfilenode ||') as text), cast('''''|| p3 ||''''' as text) from pg_class c1, pg_index i, pg_class c2, pg_namespace n where c1.oid = i.indexrelid and i.indrelid = c2.oid and c2.relnamespace = n.oid and c1.relfilenode = '|| relfilenode ||';''';
               
            raise notice 'query_str3 is:% ',query_str3;

                  RETURN QUERY EXECUTE (query_str3); 
                END IF;
                
              END LOOP;

              --表,分区表
        judge_str2 := 'EXECUTE DIRECT ON ('|| node_name ||')''select parttype from pg_partition where relfilenode = '||relfilenode||';'''; 
              FOR row_name2 IN EXECUTE(judge_str2) LOOP
                
                IF row_name2.parttype <> 'x' THEN
            
            query_str2 := 'EXECUTE DIRECT ON ('|| node_name ||')''select n.nspname, c.relname, p.relname, cast(pg_relation_filepath('|| relfilenode ||') as text), cast('''''|| p2 ||''''' as text) from pg_partition p, pg_namespace n, pg_class c where p.parentid = c.oid and c.relnamespace = n.oid and p.relfilenode = '|| relfilenode ||';''';
            raise notice 'query_str2 is:% ',query_str2;

                  RETURN QUERY EXECUTE (query_str2);
                
                ELSE
                --分区索引
                  query_str4 := 'EXECUTE DIRECT ON ('|| node_name ||')''select n.nspname, c.relname, p.relname, cast(pg_relation_filepath('|| relfilenode ||') as text), cast('''''|| p4 ||''''' as text) from pg_partition p, pg_namespace n, pg_class c, pg_index i where p.parentid = i.indexrelid and i.indrelid = c.oid and c.relnamespace = n.oid and p.relfilenode = '|| relfilenode ||';''';
               
            raise notice 'query_str4 is:% ',query_str4;

                  RETURN QUERY EXECUTE (query_str4); 
                
                  
                END IF; 
                
              END LOOP;
                                                                  
    END;$$


3、在测试数据节点dn_6001_6002获取测试用relfilenode

1>、lhk表relfilenode--732887

2>、lhk表主键索引relfilenode--732893

3>、lhk_p分区表relfilenode--741099、741100、741101、741097、741098

4>、lhk_p分区表索引relfilenode--741118、741119、741120、741121、741122


4、使用自定义函数查询

1>、relfilenode对应表文件,且表非分区

select * from public.pg_relfilenode_find(732887,'dn_6001_6002');

11.png

2>、relfilenode对应索引文件,且索引对应表非分区

select * from public.pg_relfilenode_find(732893,'dn_6001_6002');

22.png

3>、relfilenode对应表文件,且表分区

select * from public.pg_relfilenode_find(741100,'dn_6001_6002');

33.png

4>、relfilenode对应索引文件,且索引对应表分区

 select * from public.pg_relfilenode_find(741119,'dn_6001_6002');

44.png


5、如果函数没有找到数据,则可参考以下链接第5、6步骤查询判断

【总结】如何根据relfilenode查找表名 :https://bbs.huaweicloud.com/forum/thread-94650-1-1.html

注:

  • 文件如143345_bcm, 143345_C1.0, 143345.1的relfilenode都是143345;其中_bcm是特殊的文件后缀,_C1表示是列存表第一列对应的文件,*.1表示文件超过1G后新建的文件;

  • 不同实例下相同表的relfilenode可能不同;

  • 每个数据库下都有pg_class和pg_partition的系统表

  • 一定要确保连接正确的实例和数据库

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

举报
请填写举报理由
0/200