什么是 Postgres OID? 它们为什么有用?

我正在看一些 PostgreSQL 表的创建,我偶然发现了这个:

CREATE TABLE (
...
) WITH ( OIDS = FALSE );

我阅读了 postgres 提供的文档,我知道 OOP 中对象标识符的概念,但我仍然没有掌握,

  • 为什么这样的标识符在数据库中是有用的?
  • 来缩短查询时间?
  • 何时使用?
133222 次浏览

OID 基本上为系统列中包含的每一行提供一个内置 id (与用户空间列相反)。对于没有主键、有重复行等的表来说,这非常方便。例如,如果您有一个具有两个相同行的表,并且希望删除两行中最老的一行,那么可以使用 oid 列进行删除。

OID 使用4字节无符号整数实现。他们是 没有独特-OID 计数器将围绕在232-1。OID 还用于标识数据类型(参见 /usr/include/postgresql/server/catalog/pg_type_d.h)。

根据我的经验,这个特性在大多数 postgres 支持的应用程序中通常不被使用(可能部分是因为它们是非标准的) ,而且 它们的使用基本上是不被推崇的:

在 PostgreSQL 8.1中,default _ with _ oid 是 默认关闭; 在以前的版本中 PostgreSQL,默认情况下是打开的。

在用户表中使用 OID 是 被认为是不受欢迎的,所以大多数 装置应该离开这里 变量禁用。应用程序 需要特定表的 OID 创建 WITHOIDS 时应指定 WITHOIDS 这个变量可以是 为与旧版本兼容而启用 不遵循此规则的应用程序 行为。

OID 仍然用于 Postgres 大型 物品(尽管有些人认为大型对象通常并不有用)。它们也被 系统表广泛使用。例如,干杯将大于8KB 的 BYTEA (等等)存储到一个单独的存储区域(透明的) ,这是 所有桌子默认使用的。它们与“普通”用户表的直接使用基本上是 不赞成

Oid 类型当前实现为一个无符号四字节整数。因此,它不够大,无法在大型数据库,甚至在大型单个表中提供数据库范围的唯一性。因此,不建议使用用户创建的表的 OID 列作为主键。OID 最好只用于对系统表的引用。

显然,如果 OID 序列超过4B 6,那么 OID 序列“确实”包装。所以本质上它是一个可以包装的全局计数器。如果进行了包装,在使用和“搜索”唯一值时可能会出现一些减速,等等。

参见 https://wiki.postgresql.org/wiki/FAQ#What_is_an_OID.3F

要从数据库表中删除所有 OID,可以使用以下 Linux 脚本:

首先,作为 PostgreSQL 超级用户登录:

sudo su postgres

现在运行这个脚本,用您的数据库名称更改您的 _ DATABASE _ NAME:

for tbl in `psql -qAt -c "select schemaname || '.' || tablename from pg_tables WHERE schemaname <> 'pg_catalog' AND schemaname <> 'information_schema';" YOUR_DATABASE_NAME` ; do  psql -c "alter table $tbl SET WITHOUT OIDS" YOUR_DATABASE_NAME ; done

我使用这个脚本删除了所有的 OID,因为 Npgsql 3.0不能使用它,而且它对 PostgreSQL 也不再重要。

OID 正在逐步淘汰

负责 Postgres 的核心团队正在逐步淘汰 OID。

Postgres 12删除 OID 列的特殊行为

OID 作为表上可选的系统列的用法现在从 Postgres 12中删除了。你不能再使用:

  • CREATE TABLE … WITH OIDS指令
  • default_with_oids (boolean)兼容性设置

数据类型 OID保留在 Postgres 12中。可以显式创建类型 OID的列。

移民到 Postgres 12之后,默认情况下任何可选定义的 系统柱系统柱oid将不再不可见。执行 SELECT *现在将包括此列。请注意,这个额外的“惊喜”列可能会破坏纯编写的 SQL 代码。

如果您仍然使用 OID,最好删除对它的依赖,因为在 Postgres 的最新版本中,它不再受支持。 例如,这可以停止(暂时停止,直到您解决它)从版本10到版本12的迁移。

参见: Https://dev.to/rafaelbernard/postgresql-pgupgrade-from-10-to-12-566i