4

我正在 Heroku 上构建一个基本的 Rails 应用程序(使用 postgresql 和作为数据库客户端 PGAdmin)

我有一个基本的用户表,其中包含姓名、电子邮件、密码......

我注意到当我删除一个用户(例如 id = 6 的用户)然后我添加新用户时,新用户没有插入到 id=6 上(我说的是左边的第一列调用pgadmin "id PK Serial") 所以基本上我有很多漏洞,因为在我的培训期间我经常删除和添加用户。

所以我最终得到了 id 列:id=1, id=5, id=9 id= 10...很多洞。

有关系吗?它会影响对我以后可能需要做的数据库的请求吗?

如果我需要纠正它并强制数据库“填充”所有 id 插槽,我应该怎么做?

4

2 回答 2

4

在表标识序列中出现“漏洞”是绝对正常的——即使您从未删除过一行。我在这个较早的答案中写了更多关于这个的内容。

PostgreSQL 序列在设计上不受常规事务规则的约束。如果它们不是,那么一次只有一个事务可以获取一个 ID,因此您永远不能一次将多个会话插入到表中。这将导致糟糕的表现。

这在PostgreSQL 手册中的nextval调用中进行了解释- 从序列中获取值的调用:

重要:为了避免阻塞从相同序列中获取数字的并发事务,nextval 操作永远不会回滚;也就是说,一旦获取了一个值,它就被认为是已使用的,即使执行 nextval 的事务稍后中止。这意味着中止的事务可能会在分配的值序列中留下未使用的“漏洞”。

理论上 PostgreSQL 可以维护一个已删除、废弃和未使用的 ID 列表,但实际上这在性能方面非常昂贵 - 并且极难实现。一旦应用程序获得了协议id,它就可以在未来的任何时候nextval免费使用它,并且一些应用程序正是使用这种方法,缓存 ID 块以获得更好的内部并发性。

将生成的 ID 视为唯一的行号 - 仅此而已。它不会告诉你有多少行。它不会告诉您是否在另一行之后插入了一行(您可以为此使用created_time可能由触发器维护的时间戳)。它不会告诉您一行是否在另一行之后提交(系统xmin列会告诉您这一点,但有一定的限制)。它告诉你的只是如何找到行。

看:

于 2013-06-01T03:26:46.190 回答
1

删除后 ID 之间存在这些间隙是正常的 Rails 行为。

建议不要更改它,因为您可能想要稍后跟踪用户操作,并且想要浏览日志并找到相关的日志条目,或者您可能想要添加存储用户更改模型的历史记录的表(例如,当它被删除/更改时)。

在这两种情况下,您都不想因为两个不同的实例使用相同的 ID 而导致混淆——因此:不要重复使用 ID。

于 2013-05-31T23:14:11.340 回答