由于这篇文章https://stackoverflow.com/questions/9984196/postgresql-gapless-sequences中提到的原因,在 PostgreSQL 中序列被设计为有间隙。我的问题是:不能通过定期(比如说每天一次)检查哪些序列号未使用并将它们添加回序列中来使序列几乎没有间隙吗?
我假设当前 postgres 将一个序列实现为一个计数器,每次访问它时它都会递增。相反,它可以用一个自由值列表和一个计数器来实现。然后该序列将按如下方式工作:
# python style pseudo code
class Sequence:
def __init__(self):
self.free_numbers_set = []
self.counter = 0
def get_next_sequence_value(self):
if not isempty(self.free_numbers_set):
id = self.free_numbers_set.pop(0)
else:
id = self.counter
id ++
return id
def add_free_numbers(self, column):
for i in range(0:self.counter):
if not i in column:
free_numbers_set.append(i)
free_numbers_set.sort()
每次我们需要一个新的 id 时,我们都会运行get_next_sequence_value()
并定期运行add_free_numbers(column)
更新解决了一些问题
- 对于标识列,获取当前使用的值将是微不足道的。在其他情况下,由用户提供已在使用的值列表。
- 需要考虑与 MVCC 的交互。可以潜在地实现它,以便在缺失值更新期间,序列将默认为仅递增计数器 - 这将避免冲突。
我相信这个解决方案可以提供更少的稀疏序列,这将允许用户使用更小的 id 类型(int vs bigint),同时向后兼容当前的实现。
问题是无法确定序列的使用方式和位置。它不必
DEFAULT
是拥有序列的列的子句:nextval
可以在任何地方调用并以创造性的方式使用,甚至在数据库之外。即使您只考虑标识列的情况,扫描表以查找“缺失值”也会非常昂贵,并且不清楚应该如何与 MVCC 交互。
最后,我看到的大多数对无间隙序列的请求都要求单调递增的值,而这个解决方案不会提供。