4、关系型数据库元数据采集(下):PostgreSQL 与 Oracle 元数据采集要点

上一章我们聊了 MySQL 的采集套路。这一章,咱们把目光转向 PostgreSQL 和 Oracle。

说实话,这两个数据库在元数据采集上,比 MySQL 要「讲究」一些。PG 的 information_schema 很标准,但有些关键信息藏在系统表里。Oracle 呢,嗯,它的数据字典庞大得像个迷宫,我第一次接触时也绕了不少弯路。

今天我就把这两套系统的采集要点拆开揉碎了讲给你听。你想想看,搞懂了它们的脾性,以后不管换什么数据库,心里都有底。

4.1 PostgreSQL:标准与扩展并存

PostgreSQL 的元数据体系,说白了就是两条腿走路:一条是 SQL 标准定义的 information_schema,另一条是 PG 自己的系统表(pg_catalog)。

我个人习惯,能用 information_schema 的绝不动系统表。但有些场景,比如获取表的物理存储大小、索引的详细定义,你就得去翻 pg_catalog 了。

4.1.1 核心采集对象与 SQL

我们先看最常用的几个采集点。我把它们整理成了一张表,方便你对照着用。

采集目标 核心视图/表 关键字段
数据库列表 pg_database datname, datdba, encoding
模式列表 information_schema.schemata schema_name, schema_owner
表与视图 information_schema.tables table_name, table_type, table_schema
字段信息 information_schema.columns column_name, data_type, is_nullable
主键约束 information_schema.table_constraints + key_column_usage constraint_name, column_name
索引信息 pg_indexes indexname, indexdef, tablespace
表大小 pg_table_size(), pg_total_relation_size() 函数返回值(bytes)

举个例子,采集某个模式下所有表的字段信息,我会这么写:

SELECT
    c.table_schema,
    c.table_name,
    c.column_name,
    c.data_type,
    c.character_maximum_length,
    c.is_nullable,
    c.column_default
FROM information_schema.columns c
WHERE c.table_schema NOT IN ('pg_catalog', 'information_schema')
ORDER BY c.table_schema, c.table_name, c.ordinal_position;
小提示: PG 的 information_schema 查询速度通常不错。但如果你的数据库里有几千张表,记得给 table_schema 和 table_name 加上索引,否则第一次全量采集可能会有点慢。

4.1.2 避坑:系统表与权限

我曾经在一个生产环境上踩过坑。当时用 pg_catalog.pg_class 去拿表的 OID,结果发现有些表查不到。后来一查,原来是采集账号没有 pg_catalog 模式的使用权限。

所以,这里有个原则:优先用 information_schema。它只返回当前用户有权限看到的对象,不容易出权限问题。如果非要用系统表,记得给账号加上 pg_read_all_stats 或类似角色。

4.2 Oracle:数据字典的庞大家族

Oracle 的元数据采集,嗯,怎么说呢,它更像是在跟一个老派的贵族打交道——规矩多,但功能强大。

Oracle 的数据字典分为三类视图:USER_、ALL_ 和 DBA_。我个人建议,能用 ALL_ 就别用 DBA_,除非你确实需要全局视角。因为 DBA_ 视图通常需要更高的权限,而且查询开销更大。

4.2.1 核心采集对象与 SQL

Oracle 的采集重点,除了表、字段、索引这些常规项,还有几个特有的东西:表空间、分区表和物化视图。下面这张表帮你理清脉络。

采集目标 核心视图 关键字段
用户/模式 ALL_USERS username, created
表与视图 ALL_TABLES, ALL_VIEWS table_name, owner, tablespace_name
字段信息 ALL_TAB_COLUMNS column_name, data_type, data_length
约束信息 ALL_CONSTRAINTS + ALL_CONS_COLUMNS constraint_type, column_name
索引信息 ALL_INDEXES + ALL_IND_COLUMNS index_name, uniqueness, column_position
表空间 DBA_TABLESPACES tablespace_name, block_size, status
分区信息 ALL_TAB_PARTITIONS partition_name, high_value, num_rows

比如,采集某个用户下所有表的字段信息,我会这样写:

SELECT
    tc.owner,
    tc.table_name,
    tc.column_name,
    tc.data_type,
    tc.data_length,
    tc.data_precision,
    tc.data_scale,
    tc.nullable
FROM ALL_TAB_COLUMNS tc
WHERE tc.owner = 'YOUR_SCHEMA'
ORDER BY tc.table_name, tc.column_id;
注意: Oracle 的 ALL_TAB_COLUMNS 中,data_length 是字节长度,data_precision 和 data_scale 才是数字类型的精度和小数位。别搞混了,否则采集到的元数据会误导下游的数据建模。

4.2.2 避坑:分区表与 LOB 字段

Oracle 的分区表是个好东西,但采集元数据时容易出问题。你想想看,一张分区表可能有几百个分区,如果每个分区都当成独立表去采集,那元数据量会爆炸。

我曾经接手过一个项目,之前的采集脚本把每个分区都当成一张表,结果元数据仓库里多了几万条「假表」记录。后来我改成了只采集分区表的父表信息,分区细节通过 ALL_TAB_PARTITIONS 单独存储,这才把问题解决。

另外,LOB 字段(如 CLOB、BLOB)在 ALL_TAB_COLUMNS 里也能查到,但它们的 data_length 通常是 4000 或一个固定值,并不代表实际存储大小。如果你需要统计 LOB 段的存储量,得去查 DBA_LOBS 或 ALL_LOBS。

4.3 两种数据库的采集策略对比

为了方便你选型,我把 PG 和 Oracle 的采集策略做了个对比。说白了,就是帮你判断:什么时候该用哪种方式。

对比维度 PostgreSQL Oracle
标准兼容性 高(information_schema 完整) 低(以自有视图为主)
权限模型 基于模式(schema) 基于用户(schema = user)
性能瓶颈 系统表扫描(pg_catalog) DBA_ 视图全量查询
特有采集项 表大小函数、自定义类型 表空间、分区、物化视图
推荐采集方式 information_schema + 少量 pg_catalog ALL_ 视图 + 按需使用 DBA_

4.4 本章知识体系图

下面这张图,帮你把 PG 和 Oracle 的采集要点串起来。你可以把它当成一个快速索引,以后做采集时直接对照着看。

关系型数据库元数据采集要点(PG & Oracle) 采集核心目标 PostgreSQL 采集要点 优先使用 information_schema 系统表 pg_catalog 补充物理信息 注意 schema 权限隔离 Oracle 采集要点 优先使用 ALL_ 视图 DBA_ 视图需高权限,谨慎使用 分区表与 LOB 字段单独处理 核心原则 1. 标准视图优先,系统表补充 2. 权限最小化,避免全量 DBA 扫描 3. 分区表、LOB 等特殊对象单独采集

4.5 本章小结

PostgreSQL 和 Oracle 的元数据采集,本质上都是在跟数据字典打交道。PG 胜在标准、清爽,Oracle 胜在全面、强大。

我个人觉得,搞懂这两个数据库的采集,你基本就能应对市面上 80% 的关系型数据库了。因为它们的思路是相通的:先找标准视图,再补系统表,最后处理特殊对象。