SQL,Postgres OIDs,它们是什么,为什么它们有用?
SQL中的OID(Object Identifier)是PostgreSQL数据库中的一种数据类型,用于标识数据库中的对象。在PostgreSQL中,OID主要用于大型对象(large objects)和系统表(system tables)。
大型对象是一种特殊类型的数据,通常包含大量二进制数据,如图像、音频或视频文件。PostgreSQL使用OID来引用和管理大型对象。大型对象存储在与普通表数据分离的存储区域中,这个存储区域称为TOAST(The Oversized-Attribute Storage Technique)。TOAST允许将超过8KB的BYTEA(二进制字符串)等较大的数据类型存储在独立的存储区域中,这样可以节省磁盘空间并提高查询性能。
在系统表中,OID被广泛使用。系统表是PostgreSQL内部使用的表,用于存储数据库元数据和其他系统信息。OID可以用于引用系统表中的行。
然而,在普通用户表中直接使用OID列作为主键是不推荐的。因为OID是一个无符号的四字节整数,不足以在大型数据库中提供全局唯一性。当使用OID作为主键时,可能会导致性能下降,并且在超过4B的情况下,OID序列会循环。
总结起来,OID在PostgreSQL中仍然用于大型对象和系统表。对于普通用户表,直接使用OID作为主键已不再推荐。
参考链接:
- [PostgreSQL官方文档 - 大型对象](http://www.postgresql.org/docs/9.4/static/largeobjects.html)
- [PostgreSQL官方文档 - 大型对象接口](http://www.postgresql.org/docs/9.4/static/lo-interfaces.html)
- [PostgreSQL官方文档 - TOAST](http://www.postgresql.org/docs/8.4/static/storage-toast.html)
- [PostgreSQL官方文档 - OID数据类型](http://www.postgresql.org/docs/9.4/static/datatype-oid.html)
- [PostgreSQL Wiki - FAQ](https://wiki.postgresql.org/wiki/FAQ#What_is_an_OID.3F)
OIDs被逐步淘汰
Postgres的核心团队正在逐步淘汰OIDs。
Postgres 12取消了OID列的特殊行为
在Postgres 12中,将不再使用OID作为表格的可选系统列。您不能再使用以下命令:
CREATE TABLE … WITH OIDS
命令default_with_oids (boolean)
兼容性设置
数据类型OID
仍然存在于Postgres 12中。您可以显式地创建一个OID
类型的列。
在迁移到Postgres 12后,任何可选定义的系统列oid
将不再默认隐藏。执行SELECT *
将包括此列。请注意,这个额外的"surprise"列可能会破坏简单编写的SQL代码。
SQL中的OID(对象标识符)是一种系统列,为每一行提供了内置的标识符。对于没有主键、有重复行等情况的表格来说,这非常方便。举个例子,如果你有一张包含两行完全相同的表格,并且你想删除其中较早的那一行,你可以使用OID列来实现。
OID使用4字节的无符号整数实现。它们不是唯一的,OID计数器在达到2³²-1后会循环。OID还用于标识数据类型。
根据我的经验,在大多数使用Postgres的应用程序中,这个功能基本上是不被使用的(可能部分原因是因为它们是非标准的),而且它们的使用已经被弃用了。在PostgreSQL 8.1中,默认情况下关闭了default_with_oids选项,而在之前的版本中,默认情况下是开启的。使用OID在用户表中被认为是不推荐的做法,因此大多数安装应该禁用这个变量。对于需要在特定表格中使用OID的应用程序,在创建表格时应该指定WITH OIDS选项。这个变量可以用于与不遵循此行为的旧应用程序的兼容性。
OIDs不能保证唯一性。根据文档:"在一个大型或长期运行的数据库中,计数器可能会循环。因此,假设OID是唯一的是不好的做法,除非你采取措施确保这一点。"
循环使用还意味着不能仅仅基于OID删除两行中的较旧行,因为较低的OID可能是循环的结果。
OIDs不是全局唯一的,正如上述评论所述,即使在2011年撰写这篇回答时也是如此。此外,系统对象需要使用OID,因此在行计数器上使用所有OID并不能帮助数据库为新表格(而不仅仅是表格的行)分配OID。此外,考虑一下,一个4字节的整数计数器是否足以满足数据库中每个表格的需求。
值得一提的是,在大多数phpPgAdmin的实现中,创建表格时,默认情况下选中了禁用选项,实际上意味着这个选项已经被弃用了。
如果你不知道OID的用途,那么你可能不应该使用它们。
对于你的论点,不适用。确保唯一性与字段长度无关。通过拒绝以控制的方式分配已经被使用的值,比如抛出错误,固定长度字段可以被保证是唯一的,而不仅仅是静默地循环计数器。我们在DDL中有一个唯一关键字的原因,我们可以选择使用它或不使用它。