系统表可以按照功能分为几大类:
- 系统目录(System Catalogs):描述数据库对象,如表、列、索引、约束、命名空间。
- 事务与存储元数据:事务状态、表存储参数、分区信息等。
- 权限与安全元数据:用户、角色、权限、行级安全策略。
- 运行时统计与监控视图:数据库连接、锁、后台进程、SQL 执行统计。
- GaussDB 扩展目录:分布式节点、分区、存储引擎、在线 DDL 等特有功能(具体名称和字段取决于版本及部署形态)。
需要区分:真正的系统表(catalog tables)、系统视图(views)、函数和底层存储文件。比如 pg_class 是系统目录表,而 pg_stat_activity 通常是基于系统信息提供的统计视图,并不等价于普通物理表。
下面以 PostgreSQL 兼容内核和 GaussDB 常见目录结构为基础介绍。GaussDB 不同版本(尤其是企业版、分布式部署、openGauss 衍生版本)可能存在目录扩展或字段差异,具体以你的源码和目标版本为准。
一、最核心的系统目录:表结构与对象定义
如果你要从数据库内核源码出发,建议先掌握下面这组表。它们构成了 PostgreSQL 系数据库的基本元数据关系。
1. pg_class
核心
关系(Relation)目录:表、索引、视图、序列、TOAST 等。
关键字段:
oid:Relation OIDrelname:关系名称relnamespace:所属 Schema 的 OIDrelkind:关系类型relam:访问方法relfilenode:物理存储文件标识relpages/reltuples:统计信息reltoastrelid:关联 TOAST 表reloptions:存储参数
内核关联:RelationData、RelationGetRelid()、RelationOpen()、rd_rel、rd_smgr 等。
例如,查询一个表是否存在、表的存储参数、关系类型,通常从 pg_class 开始。
2. pg_attribute
列(Attribute)目录:每个关系的列定义。
关键字段:
attrelid:所属关系 OIDattname:列名attnum:列号atttypid:类型 OIDatttypmod:类型修饰信息attisdropped:是否已删除attnotnull:非空约束标记
内核关联:TupleDesc、Form_pg_attribute、RelationGetDescr()、列映射与元组布局。
重点: pg_attribute 不只记录用户表的列,也包含系统列和索引等其他关系的属性条目。
3. pg_type
数据类型目录。
关键字段:
oid:类型 OIDtypname:类型名称typlen:类型长度typtype:类型类别typelem:数组元素类型typrelid:复合类型对应的关系 OID
内核关联:TypeCache、类型输入输出函数、TupleDesc、类型系统与表达式执行。
例如,pg_attribute.atttypid 通常关联 pg_type.oid。
4. pg_namespace
Schema / 命名空间目录。
关键字段:
oidnspnamenspowner
内核关联:名称解析、Schema 搜索路径、RangeVar 到关系 OID 的解析过程。
常用关联:
pg_class.relnamespace → pg_namespace.oid
典型查询:定位一张表的完整结构
SELECT
c.oid AS relid,
n.nspname AS schema_name,
c.relname,
c.relkind,
c.relam,
c.relfilenode,
c.reltablespace,
c.reloptions
FROM pg_class c
JOIN pg_namespace n
ON n.oid = c.relnamespace
WHERE n.nspname = 'public'
AND c.relname = 'your_table';
查询表的列和类型:
SELECT
a.attnum,
a.attname,
a.atttypid,
t.typname,
a.atttypmod,
a.attnotnull,
a.attisdropped
FROM pg_attribute a
JOIN pg_type t
ON t.oid = a.atttypid
WHERE a.attrelid = 'public.your_table'::regclass
AND a.attnum > 0
ORDER BY a.attnum;
二、索引、约束与 DDL 相关目录
这一组对你做 Online DDL、索引重建、表结构变更尤其重要。
5. pg_index
索引元数据。
关键字段:indexrelid、indrelid、indisunique、indisprimary、indisvalid、indisready、indkey、indpred、indexprs。
关联:pg_index.indexrelid → pg_class.oid,pg_index.indrelid → pg_class.oid。
Online DDL 重点: 索引是否有效、是否准备好接受写入、索引所属表及索引列定义,都需要结合此表和 pg_class 分析。
6. pg_constraint
约束定义。
支持主键、唯一约束、外键、CHECK 等约束。
关键字段:conname、conrelid、contype、conindid、conkey、confrelid、convalidated。
7. pg_inherits
表继承及相关父子关系。
重点用于继承树、分区父子关系等元数据分析;在不同版本中,分区的主要信息还需要结合专用分区目录。
8. pg_attrdef
列默认值定义,例如 DEFAULT nextval(...)。
与 pg_attribute 结合,可分析列默认表达式、DDL 变更后默认值元数据等。
9. pg_depend
数据库对象之间的依赖关系。
例如视图依赖表、对象依赖类型、约束依赖索引等。
DDL 内核意义: DROP、ALTER、对象重命名和依赖检查时,需要处理对象之间的依赖关系。
查询索引及索引状态
SELECT
idx.indexrelid,
idx.indrelid,
idx.indisunique,
idx.indisprimary,
idx.indisvalid,
idx.indisready,
c.relname AS index_name
FROM pg_index idx
JOIN pg_class c
ON c.oid = idx.indexrelid
WHERE idx.indrelid = 'public.your_table'::regclass;
字段和目录结构在 GaussDB 版本中可能有所扩展,建议以目标版本的 pg_index.h 和 SQL 定义为准。
三、分区表相关系统表
对于 GaussDB 分布式内核,分区元数据值得单独掌握。特别是涉及分区合并、分区交换、分区索引、分区 DDL 时。
pg_partition(GaussDB / openGauss 扩展)
在相关 GaussDB 版本中,PG_PARTITION 用于记录分区表、表分区及索引分区等信息。华为 GaussDB 分布式开发文档明确介绍了该目录及其字段。
常见需要关注的字段包括:
| 字段 | 用途 |
|---|---|
oid | 分区对象 OID |
relname | 分区对象名称 |
parttype | 对象类型 |
parentid | 父分区表或索引相关 OID |
partstrategy | 分区策略 |
relfilenode | 物理存储标识(适用的分区对象) |
具体字段和 parttype 编码需以你的 GaussDB 版本为准。
分区内核关联
建议结合以下对象和代码路径研究:
pg_class:关系的基本元数据。pg_partition:分区对象及分区层级信息。pg_attribute:分区表及其列定义。- 分区路由、分区裁剪和分区索引相关的内核结构。
- 分区 DDL 执行器、锁管理、缓存失效及元数据更新。
重要区别: 不要把 pg_class 中的普通表信息与 GaussDB 扩展的分区目录信息视为完全等价。分区目录通常提供更具体的分区对象元数据。
四、统计信息与优化器相关系统表
10. pg_statistic
保存优化器使用的列统计信息。
主要用于:
-
直方图(Histogram)
-
最常见值(MCV)
-
NULL 比例
-
不同值估计
-
相关统计信息
内核关联:
-
ANALYZE -
优化器估算
-
选择性估计
-
统计信息缓存
-
扩展统计信息(如果版本支持)
GaussDB 的具体统计目录和字段可能存在扩展,应检查对应版本。
11. pg_stats(系统视图)
提供更便于查询的统计信息视图。它不是与 pg_statistic 完全同一种底层存储对象。
12. pg_statistic_ext(适用版本)
扩展统计信息定义,例如多列相关性统计信息。不同 GaussDB 分支的支持情况可能不同。
五、事务、存储与数据库级元数据
这一组不全是事务日志内部结构,但对数据库存储内核研究很有帮助。
13. pg_database
数据库级信息。
例如数据库名称、所有者、编码、默认表空间等。
注意: 它属于集群共享的系统目录类型,与只在单个数据库内存在的普通系统目录不同。
14. pg_tablespace
表空间元数据。
适用于分析关系与表空间之间的关联、存储位置以及相关 DDL 行为。
可结合 pg_class.reltablespace 使用。
15. pg_db_role_setting
保存数据库级别、角色级别的配置参数设置。
用于分析特定数据库或角色的参数覆盖。
需要特别区分:系统目录 vs 事务内部存储
pg_class 中的 relfrozenxid、relminmxid 等字段涉及事务 ID 老化和冻结进度;它们与事务管理器、VACUUM、事务 ID 回收机制有关。
但以下内容通常不是普通 SQL 可查询的系统目录表:
-
pg_xact:事务提交状态存储目录。 -
pg_multixact:多事务相关存储目录。 -
pg_subtrans:子事务相关存储目录。 -
pg_wal:WAL 日志存储目录(目录名称与版本及实现有关)。
对于 GaussDB 的 UHeap、Undo、CLOG/CSNLOG 等扩展,不能简单假设其实现完全等同于原生 PostgreSQL;应直接查看对应版本的事务管理与存储代码。
六、权限与角色相关系统表
16. pg_authid
角色(Role)及认证标识信息。
常见字段包括:
-
oid -
rolname -
rolsuper -
rolinherit -
rolcreaterole -
rolcreatedb -
rolcanlogin
其中部分字段包含敏感的认证信息,权限控制需要特别注意。
17. pg_auth_members
角色成员关系。
用于分析:
-
角色继承
-
角色成员资格
-
权限传递路径
18. pg_default_acl
默认权限定义。
例如创建新表时的默认权限设置。
内核开发关注点
如果你要实现 Online DDL 进度信息的权限隔离,除了自定义函数本身的权限检查,还应研究:
-
当前用户和角色身份的获取方式。
-
系统目录访问权限。
-
系统视图的定义与安全边界。
-
分布式场景下 CN / DN 的权限执行位置。
具体安全策略需要结合 GaussDB 版本的认证授权实现,而不是直接假设原生 PostgreSQL 的行为完全适用。
七、函数、操作符与表达式系统表
这一组是理解 SQL 解析、类型推导、表达式执行和函数调用的重要基础。
| 系统目录 | 主要作用 |
|---|---|
pg_proc | 函数与存储过程定义 |
pg_operator | 操作符定义 |
pg_opclass | 索引操作类 |
pg_am | 访问方法定义 |
pg_amop | 访问方法操作符关系 |
pg_amproc | 访问方法支持函数 |
pg_cast | 类型转换定义 |
pg_language | 过程语言定义 |
pg_aggregate | 聚合函数定义 |
对数据库内核最值得关注的三个
pg_proc
函数定义与函数 OID 解析密切相关。你通过 SPI_execute 调用内部 SQL 函数、注册新的系统函数时,需要理解函数目录和函数解析过程。
pg_am
访问方法目录。结合 pg_class.relam、索引访问方法接口,可以研究 B-tree、Hash 以及数据库扩展的访问方法。
pg_opclass / pg_amop / pg_amproc
索引操作类及支持函数相关元数据。对于新增索引类型、修改索引操作符语义或研究优化器索引匹配逻辑很重要。
八、运行时监控视图:不是传统系统目录,但实际非常关键
如果你的目标是实现 gs_stat_progress_online_ddl(),这组对象应该重点研究。
| 对象 | 作用 |
|---|---|
pg_stat_activity | 会话、当前 SQL、事务状态等 |
pg_locks | 锁信息 |
pg_stat_database | 数据库级统计 |
pg_stat_all_tables | 表级访问与维护统计 |
pg_stat_all_indexes | 索引级统计 |
pg_stat_progress_vacuum | VACUUM 进度 |
pg_stat_progress_create_index | 创建索引进度(适用版本) |
与普通系统目录的区别: 这些通常是系统视图或动态统计接口,反映运行时状态,而不是所有信息都由一个普通、持久化的目录表直接存储。
Online DDL 进度功能可以借鉴什么?
建议重点研究以下设计点:
-
进度数据模型:任务 ID、对象标识、阶段、开始时间、完成时间、进度计数器。
-
访问权限:不同角色是否能看到其他用户的任务。
-
快照一致性:多个 DDL 内部阶段状态的读取是否需要一致性保证。
-
并发访问:进度记录更新与 DDL 清理、事务结束之间的锁关系。
-
CN / DN 可见性:分布式执行时,统计数据是集中收集还是各节点分别查询。
九、GaussDB 分布式扩展目录:需要按版本核对
这是和原生 PostgreSQL 差异最值得深入的部分。
pgxc_node
在采用 PGXC/openGauss 风格分布式架构的相关版本中,用于描述集群节点元数据。常见研究方向包括:
-
CN / DN 节点信息
-
节点 OID
-
节点类型及角色
-
节点连接与分布式执行相关元数据
注意: 不能在未确认版本的情况下,直接将某个 openGauss 分支的字段或目录布局视为你正在使用的 GaussDB 企业版实现。
pgxc_group / pgxc_class 等
部分分布式版本可能提供节点组、分布键或分布式关系元数据相关目录。
对于这些表,建议从源码和实际数据库中的目录定义出发确认:
-
表是否存在。
-
字段类型和语义。
-
是否 CN / DN 上都存在。
-
是否允许普通用户访问。
-
目录更新发生在哪个执行节点。
-
分布式事务或 DDL 操作是否需要同步元数据。
系统目录定义
│
├── pg_class / pg_attribute / pg_type
│ │
│ └── Relation / TupleDesc / relcache
│
├── pg_index / pg_constraint
│ │
│ └── 索引与约束 / DDL 依赖
│
├── pg_partition
│ │
│ └── 分区元数据 / 分区 DDL
│
├── pgxc_*(适用版本)
│ │
│ └── 分布式元数据 / CN-DN 执行
│
└── pg_stat_* / 进度视图
│
└── 运行时统计 / Online DDL 监控
十、在 GaussDB 环境中确认实际存在的系统表
不要只依赖 PostgreSQL 文档或其他 GaussDB 版本的目录清单。对于你当前的闭源 GaussDB Kernel,最可靠的方式是直接查看运行中的数据库目录。
1. 列出系统目录与视图
SQL
SELECT
n.nspname AS schema_name,
c.relname,
c.relkind,
c.oid
FROM pg_class c
JOIN pg_namespace n
ON n.oid = c.relnamespace
WHERE n.nspname IN ('pg_catalog', 'pg_toast')
ORDER BY n.nspname, c.relname;
2. 查询某个系统表的实际字段
SELECT
a.attnum,
a.attname,
format_type(a.atttypid, a.atttypmod) AS data_type,
a.attnotnull,
a.attisdropped
FROM pg_attribute a
WHERE a.attrelid = 'pg_catalog.pg_class'::regclass
AND a.attnum > 0
ORDER BY a.attnum;
对于 GaussDB 扩展表,可以将 pg_class 替换为要检查的对象名称;如果目标对象是版本特有目录,先确认其存在。
3. 从源码搜索目录定义
如果你有 GaussDB Kernel 源码,建议重点搜索:
rg "CATALOG\(pg_class" src/
rg "CATALOG\(pg_partition" src/
rg "FormData_pg_class" src/
rg "Anum_pg_class" src/
rg "RelationGetDescr" src/
GaussDB 目录可能包含 PostgreSQL 原生目录定义以及额外的本地扩展。具体路径应根据你的源码树进行调整。
进一步深入
如果你准备继续研究,我建议下一步重点看:
pg_class + Relcache
从系统目录元数据到 RelationData、缓存与 DDL 更新。
pg_partition + 分区内核
分区元数据、分区索引和 DDL 更新路径。
GaussDB 分布式系统目录
CN/DN、节点元数据、分布式关系与目录一致性。
系统目录与 Online DDL
如何设计进度表、统计视图、权限和并发读取。
参考资料:
-
PostgreSQL 系统目录概览 :原生目录的整体分类和用途。
-
GaussDB PG_CLASS 文档 :GaussDB 系统表字段说明。
-
GaussDB Distributed Developer Guide :分布式版本中
PG_PARTITION等系统目录相关说明。