PostgreSQL 在内部使用对象标识符 (OID)作为各种系统表的主键.同时,系统还给用户创建的表增加一个 OID 系统字段(除非在建表时声明了 WITHOUT OIDS).类型 oid 代表一个对象标识符.除此以外还有几个 oid 的别名∶ regproc,regprocedure,regoper, regoperat或者,regclass,和 regtype. Table 5-20 显示了概要。
目前 oid 类型是用一个无符号的四字节整数实现的. 因此,它是不够用于提供大数据库范围内的唯一性保证的, 甚至在单个的大表中也不行.因此,我们不鼓励在用户创建的表中 使用 OID 字段做主键.OID 最好只是用于引用系统表.
oid 类型本身除了比较(是用无符号比较实现的)之外还有几个操作. 不过,它可以转换为整数,然后用标准的整数操作符操作.(如果你这么干, 那么请注意可能的有符号和无符号之间的混淆.)
oid 别名类型没有自己的操作,除指明的输入和输出过程之外. 这些过程可以为系统对象接受和显示符号名,而不仅仅是类型 oid 将要使用的行数值.别名类型允许我们简化为对象查找 OID 值的过程∶ 比如,我们可以写 'mytable'::regclass 以获取表 mytable 的 OID,而不是 SELECT oid FROM pg_class WHERE relname = 'mytable'. (实际上,如果在不同的大纲里有多个叫 mytable 的表, 我们就需要一个更复杂的SELECT来处理从系统表中选出正确的 OID 的工作.)
Table 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 或 regoperat或者 更合适.对于 regoperat或者,单目操作符是通过在那些未用的操作数 上写NONE来标识的.
OID 是 32 位的量,是在单一的集群范围内赋值的计数器.在一个大型或者是 长时间运行的数据库里,这个计数器很可能重叠.因此,假设 OID 是唯一的 做法不可取,除非你采取步骤保证它们是唯一的.当你使用 OID 做行标识符是, 我们建议的做法是在准备使用 OID 的表的 OID 字段上建立一个唯一约束. 绝对不要假设表与表之间的 OID 是唯一的;你可以使用 tableoid 和行 OID 的组合来实现数据库范围内的标识符. (将来的 PostgreSQL 很可能为每个表使用独立的 OID 计数器,因此在一个全局的唯一标识中必需包括 tableoid.)
系统使用的另外一个标识符类型是 xid,或者说是事务(缩写xact) 标识符.它是系统字段 xmin 和 xmax 的 数据类型.事务标识符是 32 位的量.在一个长时间的数据库中, 事务 ID 很可能重叠.我们只要采取一些合适的维护过程,这个问题事实上 不是什么大问题;参阅 PostgreSQL 7.3.3 管理员手册 获取细节. 不过,长时间倚赖事务 ID 的唯一性是不明智的做法(超过十亿次事务).
系统需要的第三种标识符类型是 cid,或者命令标识符. 它是系统字段 cmin 和 cmax 的数据类型. 命令标识符也是 32 位的量.这样,在一次事务中就有了最多执行 232 (四十亿条)SQL命令的硬上限. 在现实中,这个上限不是什么问题 --- 请注意这个上限是SQL查询的 数目,而不是处理的元组数目.
系统使用的最后的标识符类型是 tid,或者说是元组标识符. 它是系统表字段 ctid 的数据类型.元组 ID 是一对儿数值 (块号,块内的元组索引),它标识该元组在其所在表内的物理位置.