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


161

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

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

我阅读了postgres提供的文档,并且了解了OOP中的对象标识符的概念,但仍然不了解,

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

目前,我找不到任何要引用的引用,但是仅供参考,我已经知道使用Microsoft Access作为Postgres的前端需要old系统列的存在。
罗勒·布尔克

Answers:


165

OID基本上为您提供了系统列(与用户空间列相对)中包含的每行内置的全局唯一ID。对于没有主键,重复的行等的表,这很方便。例如,如果您的表中有两行相同,并且您想删除两行中最旧的行,则可以使用oid列。

根据我的经验,该功能通常在大多数支持Postgres的应用程序中未使用(可能部分是因为它们是非标准的),并且基本上不赞成使用它们

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

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


33
oid不能保证是唯一的。从文档中可以得出:“在大型或长期存在的数据库中,计数器可能会卷起来。因此,除非您采取措施确保确实如此,否则认为OID是唯一的是一种不好的做法。”
radiospiel 2013年

8
换行还意味着您不必仅根据其OID删除两行中的旧行,因为OID较低的那一行可能是换行。
卡尔·G

根据以上评论,OID并非全球唯一,2011年撰写此答案时也不是唯一。同样,系统对象也需要OID,因此用尽行计数器上的所有OID并不能帮助数据库将OID分配给新表(对于表,而不是对表的行)。另外,请考虑一个4字节整数计数器对于数据库中的每个表是否真的足够了。
FuzzyChef 2015年

值得一提的是,在创建表的大多数phpPgAdmin实现中,默认情况下选中该选项为disable,这实际上意味着已弃用该选项。
vdegenne

3
如果您不知道使用什么OID,那么您可能不想使用它们。
vdegenne '16

16

OID仍用于带有对象的 Postgres (尽管有些人认为大对象通常还是不有用的)。它们也被系统表广泛使用。例如,TOAST使用它们,TOAST将大于8KB的BYTEA(等)存储到一个单独的存储区域(透明),所有表默认使用该存储区域。与“普通”用户表相关联的直接使用基本上弃用

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

显然,如果OID序列超过4B 6,则会“包装” 。因此,从本质上讲,这是可以包装的全局计数器。如果自动换行,则在使用它并“搜索”唯一值等时,可能会开始出现一些减速。

另请参阅https://wiki.postgresql.org/wiki/FAQ#What_is_an_OID.3F


9

OID正在逐步淘汰

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

Postgres 12删除OID列的特殊行为

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

  • CREATE TABLE … WITH OIDS 命令
  • default_with_oids (boolean) 相容性设定

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

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


5

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

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

sudo su postgres

现在运行此脚本,使用您的数据库名称更改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

我使用此脚本删除了所有OID,因为Npgsql 3.0对此不起作用,并且它对PostgreSQL也不再重要。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.