【问题标题】:Efficient way to store reorderable items in a database [closed]在数据库中存储可重新排序项目的有效方法[关闭]
【发布时间】:2013-02-27 17:16:47
【问题描述】:

所以我有一张用户收藏的表格。它们有几百万行。

目前,它们只有三列:id(pk)、userIdsomeFkRefuserId 上有一个索引,可以让我快速选择用户的收藏夹。

目前这些是由id 订购的,这实际上只是插入顺序。我们希望让用户有机会重新排序他们的最爱,很可能是通过某种拖放交互。

我的第一个(我怀疑是幼稚的)方法是简单地在userIdorder 上添加一个order 列和一个复合索引。然而,经过反思,当用户将他们的项目在列表上移动一段距离时,项目的开始位置和结束位置之间的所有中间行都需要重新计算它们的 order 列,因此也需要重新计算索引。

这(很可能)很糟糕。

在我花了很长时间试图量化到底有多糟糕之前,我想知道是否有更好的基于表格的表示,并且使用我上面描述的各种操作来操作更便宜。

【问题讨论】:

  • 我不相信您需要为新字段编制索引。
  • 一般情况下,order by ops 需要索引,不是吗?
  • @spender 不需要,但是如果您的表行很大并且您获得的结果集很大,使用索引进行排序可能会产生相当少的 I/O。
  • 这是个好问题。也许你应该让它更抽象。当您在网页上有一个可重新排序的列表并且您希望将该订单保存到数据库中时,有很多地方。

标签: sql sql-server data-structures


【解决方案1】:

对于拖放交互,更好的选择是优先事项。您可以从优先级 1、2、3 等开始,就像排序顺序一样。

但是,用户想要在 1 和 2 之间移动项目 5。瞧!给它1.5的值。无需更改其他值。索引更新负责其余的工作。

为此,需要将优先级存储为浮点数。这可能是个问题。此外,足够多的更改可能会导致浮点数的极限。因此,如果用户试图取出最后一个元素并将其插入前两个元素之间,他/她可以成功完成几十次左右。

您可以使用从 1 开始定期为一个(或所有用户,如果是批量)重新分配号码的流程来解决此问题。

【讨论】:

  • 这也是一种有价值的方法。但是你仍然需要在 someFkRef 列上有一个索引,所以它仍然会有点消耗是表非常大。
  • @SamuelEUSTACHI 索引并不是最糟糕的部分。最糟糕的是浮点数的精度有限,经过精心设计的 53 次移动后,可能会破坏排序逻辑。是的,你总是可以有一个计数器和一个触发器来重新规范这个列表,但我很不确定它是否会是一个更有效的解决方案。
【解决方案2】:

如果您不需要能够跨用户操作 someFkRef(例如,获取对某事感兴趣的用户列表),那么您可以每个用户只有一条记录,以及 someFkRef (refA,参考B)。

但这是一种去规范化的形式,并且由于它有一些缺点,它实际上取决于您的需求(以及您未来的需求,这就是麻烦所在)

【讨论】:

  • 是的,即使是同一个用户,反规范化也会打击你:a) 你需要limit/offset 并操作一个大列表; b) 这些数据通过互联网传输,用户以快速的方式对一百个元素的列表进行排序(你好,O(N2),滞后和去同步)。非规范化是一个巨大的痛苦,任何人都不应该这样做。
【解决方案3】:

不确定您对 ID 字段的依赖引用可能是什么,但您是否考虑过重写它?我认为有一个 SET IDENTITY INSERT = ON,或者你可以这样做。

我意识到这是一个奇怪的建议,但考虑到你正在尝试做的事情,它可能是有道理的,并且会导致最少的开销。

【讨论】:

  • @Joachim -- Renumber recordcount = 2 -- 仅捐赠者和接受者记录。重新索引是不确定的——大概他有一些内置的填充,并且有数百万条记录,可能是在非高峰期重新索引。
猜你喜欢
  • 1970-01-01
  • 2011-10-11
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 2017-01-06
  • 2016-03-10
  • 2022-01-21
相关资源
最近更新 更多