5.10. 对象标识符类型 #
对象标识符(OID)在
PostgreSQL 内部被用作各种系统表的主键。此外,用户创建的表也会加上一个
OID 系统列(除非建表时指定了
WITHOUT OIDS)。类型
oid 表示对象标识符。oid
还有几个别名:regproc、regprocedure、regoper、regoperator、regclass
和
regtype。表 5.20给出了一个概览。
oid 类型目前实现为无符号 4 字节整数。因此,在大型数据库中,它不足以提供数据库范围内的唯一性,甚至在大型的单个表中也无法保证唯一性。因此,不推荐把用户创建表的 OID 列用作主键。OID 最好仅用于引用系统表。
oid 类型本身除比较(实现为无符号比较)外几乎没有别的运算。不过它可以转换为
integer,然后用标准的整数运算符操作。(这样做要当心有符号与无符号之间可能的混淆。)
oid 别名类型除了专门的输入和输出例程外没有自己的运算。这些例程能够接受并显示系统对象的符号名称,而不是类型
oid
会使用的原始数值。别名类型可以简化对象 OID
值的查找:例如,可以写
'mytable'::regclass 来获得表
mytable 的 OID,而不必写
SELECT oid FROM pg_class WHERE
relname = 'mytable'。(实际上,当不同模式中有多个名为
mytable 的表时,要选出正确的
OID 需要复杂得多的
SELECT。)
表 5.20. 对象标识符类型
| 类型名 | 引用 | 描述 | 值示例 |
|---|---|---|---|
oid | 任意 | 数字形式的对象标识符 | 564182 |
regproc | pg_proc | 函数名称 | sum |
regprocedure | pg_proc | 函数与参数类型 | sum(int4) |
regoper | pg_operator | 操作符名称 | + |
regoperator | pg_operator | 带参数类型的操作符 | *(integer,integer)或-(NONE,integer) |
regclass | pg_class | 关系名称 | pg_type |
regtype | pg_type | 类型名称 | integer |
所有 OID 别名类型都接受模式限定名称;如果不加限定就无法在当前搜索路径中找到对象,输出时也会显示模式限定名称。regproc和regoper别名类型只接受唯一的(未重载的)输入名称,因此用途有限;对于大多数用途,regprocedure或regoperator更合适。对于regoperator,通过将未使用的操作数写为NONE来标识一元操作符。
OID 是 32
位的量,由一个集簇范围内的计数器分配。在一个大型或长期使用的数据库中,计数器有可能回卷。因此,除非你采取措施确保
OID 唯一,否则假定 OID
唯一是不好的做法。在用
OID 标识行时,推荐的做法是为每个要使用
OID 的表在 OID
列上创建唯一约束。绝不要假定 OID
在各表之间是唯一的;如果需要数据库范围内的标识符,应使用
tableoid 与行 OID
的组合。(PostgreSQL
的未来版本很可能为每个表使用独立的 OID
计数器,因此必须包含
tableoid 才能得到全局唯一的标识符。)
系统使用的另一种标识符类型是
xid,即事务(缩写为
xact)标识符。它是系统列
xmin 和
xmax 的数据类型。事务标识符是
32 位的量。在长期使用的数据库中,事务
ID 有可能回卷。只要有适当的维护过程,这并不是致命问题;细节见
PostgreSQL 管理员指南。但依赖事务
ID 的长期(超过十亿个事务)唯一性是不明智的。
系统使用的第三种标识符类型是
cid,即命令标识符。它是系统列
cmin 和
cmax 的数据类型。命令标识符也是
32 位的量。这给单个事务内的
SQL 命令数设定了
232(40
亿)的硬性上限。实践中这一上限不构成问题——注意该上限针对的是
SQL 命令数而不是处理的元组数。
系统使用的最后一种标识符类型是
tid,即元组标识符。它是系统列
ctid 的数据类型。元组
ID 是一个(块号,块内元组下标)对,标识元组在其表中的物理位置。