2011-04-11 112 views
104

我在看一些PostgreSQL表的创建和我偶然发现了这一点:SQL,Postgres OID,它们是什么以及它们为什么有用?

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

我读到的Postgres提供的文件和我知道,从OOP对象标识符的概念,但我仍然没有把握,

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

回答

115

OID基本上给你一个系统列(与用户空间列相对)中包含的每行的内置全局唯一标识符。对于那些没有主键,有重复行等的表格,这很方便。例如,如果你有一个有两个相同行的表,并且你想删除两个最老的表,你可以使用oid列。

以我的经验,该功能在大多数的Postgres支持的应用程序(可能部分是因为他们是非标准的)一般不使用,并their use is essentially deprecated

在PostgreSQL 8.1 default_with_oids是 默认关闭;在PostgreSQL的早期版本 中,它默认为开启。

用户表中使用OID的是 视为过时,因此大多数 安装应该离开这个 变量禁用。当创建 表时, 需要特定表的OID的应用程序 应指定WITH OIDS。此变量可以是 ,以便与不遵循此 行为的旧 应用程序兼容。

+24

oids不保证是唯一的。从文档中可以看出:“在大型数据库或长期数据库中,计数器可能会环绕,因此,假设OID是唯一的,除非您采取措施确保这种情况是错误的做法。” – radiospiel 2013-07-24 15:43:34

+7

的周围包裹也意味着你可以不必删除仅基于OID两行的年纪大了,作为一个具有较低OID可能是一个环绕式。 – 2014-04-18 17:30:33

+0

OIDs并非全球唯一,每个评论以上,也不是他们在2011年写这个答案时。另外,系统对象需要OID,因此在行计数器中使用所有OID并不能帮助数据库将OID分配给新表(对于表而不是其行)。另外,考虑单个4字节整数计数器是否真的足够用于数据库中的每个表。 – FuzzyChef 2015-01-30 21:12:26

9

OID的仍在使用Postgres的withobjects(虽然有些人会认为大对象不是一般的有用反正)。它们也被system tables广泛使用。它们被用于例如TOAST,其将大于8KB的BYTEA(等)存储到单独的存储区域(透明地),其默认使用所有表。它们与“正常”用户表关联的直接使用基本上是deprecated

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

显然,如果OID序列超过4B,则会“包裹”。所以实质上它是一个可以换行的全局计数器。如果它包装,一些减速可能开始发生,当它被使用和“搜索”唯一值,等等。

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

2

从数据库表中删除所有的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不再重要。

相关问题