【问题标题】:What should I use instead of sequence in order to avoid gaps?为了避免空白,我应该使用什么来代替顺序?
【发布时间】:2019-08-20 12:42:04
【问题描述】:

我正在开发一个允许在文件夹中组织纸质文档的系统。当文件夹已满时,用户点击“新建文件夹”按钮。此操作调用文件夹序列的nextval()

此文档表如下所示:

IDDOC FOLDER PARTNER USER
1     1      1341    56
....
700   2      4532    56

唯一的问题是序列中的文件夹编号之间的差距非常大。

我现在拥有的文件夹编号:69, 89, 109, 129, 149, 169, 209

我应该用什么代替顺序来避免它?

【问题讨论】:

  • 嗨,您可以根据需要将序列值的增量更改为 1 或 2。您也可以使用 row_number 或 dense_rank 函数。
  • 使用不带缓存参数的序列,会减少间隙。希望您仅按照@TahreemSaeed 的建议使用 1 或 2 的值递增序列
  • 何必呢? id 只是一个 id,只要它是唯一的就可以了。
  • @tahreem-saeed,是的,我使用增量 1
  • @jarlh 我同意你的观点,但是离线存档中使用了文件夹号

标签: sql oracle


【解决方案1】:

序列的主要目的是提供保证唯一标识符的来源。这些是技术关键,一般来说它们的实际价值应该是无关紧要的。我的意思是 - 你甚至需要向用户显示文件夹编号吗?

如果您对此感到困扰,请使用 NOCACHE。这将最大限度地减少您看到的差距,并且只要您不经常创建文件夹,您就不会注意到不缓存少量数字对性能的影响。如果事务回滚或由于任何其他原因失败,您仍然可能会出现差距,但它们应该不常见;如果不是,您还有比文件夹编号更重要的事情要担心!

生成单调递增序列的其他方法要么实现起来很麻烦(通过代码控制表触发),要么不能保证唯一(在触发器中使用 max(id)+1)。如果您想使用代码控制表 - 这是一个专门跟踪最后分配的文件夹 ID 的表 - 您应该看看 at a previous answer I wrote 应该如何实现一个。代码控制表的一个优点是我们可以维护一组计数。因此,您可以为每个用户运行一系列文件夹 id,并独立增加它们。

【讨论】:

  • 谢谢!我会试试NOCHACHE。文件夹编号用于在存档中存储纸质文档。存档员工知道文件夹编号后,可以轻松找到正确的文档。在这种情况下,小间隙是可以的。
  • @APC 您链接到的代码控制表解决方案非常好,但不能保证无间隙,原因与序列不是无间隙的相同:即,不能保证调用者将返回的ID 到表中并无错误地提交。我认为无缝通常是一个很差的要求,当人们意识到它的高技术成本和低商业价值时,它经常被放弃。不过,我认为也许值得一提,因为这个问题专门针对无间隙序列。
【解决方案2】:

你不能不强制你的数据库是可序列化的。由于没有并行更新,这将意味着非常糟糕的吞吐量,即每个事务都必须等待它之前的一个事务(以查看是否使用了该数字)。此外,没有回滚,因此您必须从计数器表中进行选择(也很糟糕)。

您最好忽略这些差距。如果你做不到,你可以做两件事之一。

1) 分配序列号,然后定期返回并用虚拟记录填补空白。

2) 继续做你正在做的事情,并且还有一个未分配的“真实”序列号,当你提交所有事务时,你会定期填写该序列号。

不过,一般来说,“无间隙”要求是虚假的。

【讨论】:

  • 我对这类标识符的经验是,序列化很少成为问题。用户可能每天或每周创建一次文件夹;并发更新的洪流不会发生。
  • 也许在这种情况下没问题,但作为一般模式,这不是一个好的选择。
【解决方案3】:

正如@APC 所说,序列确保唯一性。

如果您想为文件夹列设置“序列号”,请不要使用序列。您可以将“上次使用的文件夹值”存储在单独的表中,并在每次需要时手动使用它来获取一个新数字。确保在执行这些更新时将事务级别提高到 SERIALIZABLE

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-10
    • 2012-07-15
    • 2010-11-05
    • 2010-12-06
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多