前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PG中的oid和relfilenode之间的关系

PG中的oid和relfilenode之间的关系

作者头像
yzsDBA
发布2021-02-03 12:05:03
1.5K0
发布2021-02-03 12:05:03
举报

PG中的oid和relfilenode之间的关系

PG中的表由一个relfilenode值,即磁盘上表的文件名(除了外表和分区表)。通常情况下可以在Pg_class表找到这个值,然而也会查考一些表的relfilenode为0.本文介绍这些表relfilenode的内部处理流程。

普通表的relfilenode

PG中创建一个表后,会在系统被pg_class存储它的relfilenode值。下面例子,表创建后,OID和relfilenode都时16808。还可以在磁盘上看到16808文件。

postgres=# create table t2(i int);

CREATE TABLE

postgres=# select oid,relname,relfilenode frompg_class where relname = 't2';

oid | relname | relfilenode

-------+---------+-------------

16808 |t2 | 16808

(1 row)

postgres=# \q

movead@movead-PC:/h2/pgpgpg/bin$ ll../data/base/12835/16808

-rw-------+ 1 movead movead 0 12月 31 17:11../data/base/12835/16808

movead@movead-PC:/h2/pgpgpg/bin$

执行truncate、vacuum full等操作后,表数据被重写,并且表文件的relfilenode也会改变。下面测试显示了truncate后,t2的relfilenode值由16808变成16811.

代码语言:javascript
复制
postgres=# truncate t2;
代码语言:javascript
复制
TRUNCATE TABLE
代码语言:javascript
复制
postgres=# select oid,relname,relfilenode from pg_class where relname = 't2';
代码语言:javascript
复制
  oid  | relname | relfilenode
代码语言:javascript
复制
-------+---------+-------------
代码语言:javascript
复制
 16808 | t2      |       16811
代码语言:javascript
复制
(1 row)
代码语言:javascript
复制
postgres=# checkpoint;
代码语言:javascript
复制
CHECKPOINT
代码语言:javascript
复制
postgres=# \q
代码语言:javascript
复制
movead@movead-PC:/h2/pgpgpg/bin$ ll ../data/base/12835/16808
代码语言:javascript
复制
ls: 无法访问'../data/base/12835/16808': 没有那个文件或目录
代码语言:javascript
复制
movead@movead-PC:/h2/pgpgpg/bin$ ll ../data/base/12835/16811
代码语言:javascript
复制
-rw-------+ 1 movead movead 0 12月 31 17:16 ../data/base/12835/16811
代码语言:javascript
复制
movead@movead-PC:/h2/pgpgpg/bin$

nail表的relfilenode

代码语言:javascript
复制
postgres=# select oid, relname, relfilenode,reltablespace
代码语言:javascript
复制
from pg_class
代码语言:javascript
复制
where relfilenode = 0 and relkind = 'r'
代码语言:javascript
复制
order by reltablespace;
代码语言:javascript
复制
 oid  |        relname        | relfilenode | reltablespace
代码语言:javascript
复制
------+-----------------------+-------------+---------------
代码语言:javascript
复制
 1247 | pg_type               |           0 |             0
代码语言:javascript
复制
 1255 | pg_proc               |           0 |             0
代码语言:javascript
复制
 1249 | pg_attribute          |           0 |             0
代码语言:javascript
复制
 1259 | pg_class              |           0 |             0
代码语言:javascript
复制
 3592 | pg_shseclabel         |           0 |          1664
代码语言:javascript
复制
 1262 | pg_database           |           0 |          1664
代码语言:javascript
复制
 2964 | pg_db_role_setting    |           0 |          1664
代码语言:javascript
复制
 1213 | pg_tablespace         |           0 |          1664
代码语言:javascript
复制
 1261 | pg_auth_members       |           0 |          1664
代码语言:javascript
复制
 1214 | pg_shdepend           |           0 |          1664
代码语言:javascript
复制
 2396 | pg_shdescription      |           0 |          1664
代码语言:javascript
复制
 1260 | pg_authid             |           0 |          1664
代码语言:javascript
复制
 6000 | pg_replication_origin |           0 |          1664
代码语言:javascript
复制
 6100 | pg_subscription       |           0 |          1664
代码语言:javascript
复制
(14 rows)
代码语言:javascript
复制
postgres=#

上面的例子的查询可看到这些表的relfilenode都是0.pg_type、pg_proc、pg_attribute和pg_class是non-shared表,称为Nail表。剩余的表是pg_global表空间的shared表。

Pg_class表中的relfilenode字段告诉我们磁盘上存储的文件名是什么。例如在表t2上进行查询时,首先需要从pg_class中获取relfilenode,然后在磁盘上找到对于文件,接着才能进行打开和扫描。如果想查询磁盘上pg_class的文件名,那去哪里找relfilenode呢?有一系列函数提供了转换oid\relfilenode的函数。

代码语言:javascript
复制
postgres=# select pg_relation_filenode(1259);
代码语言:javascript
复制
 pg_relation_filenode
代码语言:javascript
复制
----------------------
代码语言:javascript
复制
                16475
代码语言:javascript
复制
(1 row)
代码语言:javascript
复制
postgres=# select pg_filenode_relation(0,16475);
代码语言:javascript
复制
 pg_filenode_relation
代码语言:javascript
复制
----------------------
代码语言:javascript
复制
 pg_class
代码语言:javascript
复制
(1 row)
代码语言:javascript
复制
postgres=# select pg_filenode_relation(0,16475)::oid;
代码语言:javascript
复制
 pg_filenode_relation
代码语言:javascript
复制
----------------------
代码语言:javascript
复制
                 1259
代码语言:javascript
复制
(1 row)
代码语言:javascript
复制
postgres=#

通过调用pg_relation_filenode(),oid可以转换成relfilenode;通过pg_filenode_relation()函数可以将relfilenode转换成oid。

Shared和nail表的oid和relfilenode之间的关系没有存储在pg_class表,PG如何存储这个映射关系呢?

Nail表的relfilenode存储机制

经过研究后,找到要给pg_filenode.map文件:

代码语言:javascript
复制
movead@movead-PC:/h2/pgpgpg/data/base/12835$ ll pg_filenode.map
代码语言:javascript
复制
-rw-------+ 1 movead movead 512 12月 31 15:10 pg_filenode.map
代码语言:javascript
复制
movead@movead-PC:/h2/pgpgpg/data/base/12835$
代码语言:javascript
复制
movead@movead-PC:/h2/pgpgpg/data/global$ ll pg_filenode.map
代码语言:javascript
复制
-rw-------+ 1 movead movead 512 12月 31 15:10 pg_filenode.map
代码语言:javascript
复制
movead@movead-PC:/h2/pgpgpg/data/global$

shared表的oid和relfilenode映射关系存储在global目录的pg_filenode.map中。Database为12835的nail表映射关系存储在12835目录的pg_filenode.map中。该文件存储的内容结构是:

代码语言:javascript
复制
typedef struct RelMapping
代码语言:javascript
复制
{
代码语言:javascript
复制
    Oid         mapoid;         /* OID of a catalog */
代码语言:javascript
复制
    Oid         mapfilenode;    /* its filenode number */
代码语言:javascript
复制
} RelMapping;
代码语言:javascript
复制
typedef struct RelMapFile
代码语言:javascript
复制
{
代码语言:javascript
复制
    int32       magic;          /* always RELMAPPER_FILEMAGIC */
代码语言:javascript
复制
    int32       num_mappings;   /* number of valid RelMapping entries */
代码语言:javascript
复制
    RelMapping  mappings[MAX_MAPPINGS];
代码语言:javascript
复制
    pg_crc32c   crc;            /* CRC of all above */
代码语言:javascript
复制
    int32       pad;            /* to make the struct size be 512 exactly */
代码语言:javascript
复制
} RelMapFile;

总结

本文主要介绍了PG的oid和relfilenode的两种表现方式,pg_relation_filenode()获取的值永远是正确的,但是从系统表中查询出的就可能是错误的。

原文

https://www.highgo.ca/2021/01/12/the-mapping-of-oid-and-relfilenode-in-pg/

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • PG中的oid和relfilenode之间的关系
    • 普通表的relfilenode
      • nail表的relfilenode
        • Nail表的relfilenode存储机制
          • 总结
            • 原文
            相关产品与服务
            对象存储
            对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档