SQL,Postgres OID,它们是什么以及为什么它们有用?

fab*_*ioM 147 sql database postgresql performance

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

CREATE TABLE (
...
) WITH ( OIDS = FALSE );
Run Code Online (Sandbox Code Playgroud)

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

  • 为什么这样的标识符在数据库中有用?
  • 使查询更短?
  • 什么时候应该使用?

Fra*_*mer 154

OID基本上为每行提供一个内置的,全局唯一的id,包含在系统列中(而不是用户空间列).对于没有主键,有重复行等的表格来说这很方便.例如,如果你有一个包含两个相同行的表,并且你想要删除这两行中最老的那些,你可以使用oid专栏.

根据我的经验,该功能通常在大多数postgres支持的应用程序中未使用(可能部分原因是它们是非标准的),并且它们的使用基本上已被弃用:

在PostgreSQL 8.1中,default_with_oids默认是关闭的; 在PostgreSQL的早期版本中,默认情况下它处于启用状态.

在用户表中使用OID被认为已弃用,因此大多数安装都应禁用此变量.需要OID用于特定表的应用程序应在创建表时指定WITH OIDS.可以启用此变量以与不遵循此行为的旧应用程序兼容.

  • oids不保证是独一无二的.来自文档:"在一个大型或长期存在的数据库中,计数器可能会被包围.因此,假设OID是唯一的,这是不好的做法,除非你采取措施确保这种情况." (32认同)
  • 环绕也意味着您不必仅根据其OID删除两行中较旧的行,因为具有较低OID的行可能是环绕的. (8认同)
  • 如果您不知道使用什么OID,那么您可能不想使用它们。 (3认同)
  • 根据上面的评论,OID 不是全局唯一的,在 2011 年撰写此答案时也不是。此外,系统对象需要 OID,因此用完行计数器上的所有 OID 并不能帮助数据库将 OID 分配给新表(对于表,而不是其行)。另外,请考虑单个 4 字节整数计数器是否真的足以满足数据库中的每个表的需要。 (2认同)

Bas*_*que 18

正在逐步淘汰 OID

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

Postgres 12 移除了 OID 列的特殊行为

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

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

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

迁移到的Postgres 12,任何任选地定义系统柱 oid将不再通过默认不可见的。执行 aSELECT *现在将包括此列。请注意,这个额外的“惊喜”列可能会破坏简单编写的 SQL 代码。


rog*_*ack 14

OID仍然用于具有大型物体的 Postgres (尽管有些人认为大型物体通常不是很有用).它们也被系统表广泛使用.它们例如由TOAST使用,它将大于8KB的BYTEA(等)存储到一个单独的存储区域(透明地),默认情况下由所有表使用.它们与"普通"用户表相关的直接使用基本上弃用.

oid类型当前实现为无符号的四字节整数.因此,它不足以在大型数据库或甚至大型单个表中提供数据库范围的唯一性.因此,不鼓励使用用户创建的表的OID列作为主键.OID最好仅用于对系统表的引用.

显然,如果超过4B 6,OID序列"确实"换行.所以从本质上讲,它是一个可以包装的全局计数器.如果它确实换行,当它被使用并"搜索"唯一值等时,可能会开始发生一些减速.

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


Rod*_*tto 5

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

首先,以 PostgreSQL 超级用户身份登录:

sudo su postgres
Run Code Online (Sandbox Code Playgroud)

现在运行此脚本,使用您的数据库名称更改 YOUR_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
Run Code Online (Sandbox Code Playgroud)

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