如何存储经常改变DB位置的订购商品

时间:2010-08-03 17:55:46

标签: sql data-structures recursion indexing linked-list

我需要能够在DB中存储大量订购商品。到目前为止,这是直截了当的:

ID Position OtherFields
 1     45      ...
 2   4736      ...
 3    514      ...
 ...

在查询中,我总是需要获得一些项目(基于OtherFields过滤),但顺序正确。也很简单,在位置上放置一个索引并使用“按位置排序”。

现在问题:项目频繁更改其位置,而不仅仅是1或2.如果ID 2将位置从4736更改为2000,我需要更新其位置和所有位置旧位置2000和4735之间的元素,每行添加1。而且,每个交易不仅会更改一个ID,而且会在短时间内发生许多交易。

我认为处理更新问题的最优雅的方法是使用链接列表而不是位置列,我可以通过将ID 2从其前任链接到其后继者来从旧位置删除ID 2然后通过在新的前任和后继者之间链接它将其插入其他地方。这将是每个职位变更的持续和少量更新,它也是我处理变更的首选方式(在我的案例中是Java)。然而,这会以正确的顺序引发查询的N + 1问题 - 即使对于一些元素,我必须在最坏的情况下查看整个列表以找出正确的顺序。

所以我的问题是:您建议在必要的更新和查询效果之间取得良好的平衡?

到目前为止,我看到了两个有希望的方向:

  1. 是否有DBMS(理想情况下是OpenSource)可以处理链接列表,不仅具有语法糖,而且具有良好的性能,例如:通过使用链接元素的内部指数?

  2. 也许只有一个BLOB可以存储整个链接列表的选项!这样的链接列表有多大/它在数据库中使用了多少内存,并且当获取时让我们说1.000.000条目?我正在使用Java + Hibernate以防万一。我想在获取BLOB后处理内存中的整个列表应该非常快!?

  3. 但当然也欢迎其他想法!

4 个答案:

答案 0 :(得分:28)

如果放宽约束,Position列必须包含从1到N的整数,而是允许它包含任何数字,那么您可以有效地进行搜索和更新。

您可以通过计算平均值(A + B)DIV 2在位置A和B的两个其他项目之间插入一个项目。例如,如果A是10000而B是12000,那么您的新位置是11000.偶尔您会运行由于聚类导致的间隙不足,此时您可以通过整个表格更均匀地重新分配位置。

答案 1 :(得分:5)

使用小数位置怎么样?如果这样做,您可以使用以下方法将其置于其他位置之间:

原始记录是:

ID    Position  Otherfields
--------------------------
1     1.0
2     2.0
.
.
.
5000  5000.0

然后说你将ID 1移到5000之前

ID    Position  Otherfields
--------------------------
1     4999.9
2     2.0
.
.
.
5000  5000.0

现在假设你想把ID 2放在1到5000之间:

ID    Position  Otherfields
--------------------------
1     4999.9
2     4999.91
.
.
.
5000  5000.0

这样你只会改变一条记录......

更新:

重新阅读@Mark Byers的建议后,似乎我们的解决方案非常相似,但使用小数似乎对我来说简单得多......

答案 2 :(得分:0)

另一种解决方案是使用词汇排名。只要两个字符串之间没有值,就可以简单地添加一个新字符。唯一的缺点是,与数值解答相比,它消耗更多的内存,而数值解答在其他答案中都有提及。

对没有错误的数据库而言,规范化不是必需的,但可以选择执行归一化以减少字符串长度。

这是一段有趣的视频,详细解释了它:https://www.youtube.com/watch?v=OjQv9xMoFbg&feature=youtu.be

答案 3 :(得分:-1)

以下内容可能会有所帮助。它没有直接回答你的问题,但可以说明如何做到这一点(如果你的要求可能):

ranking entries in mysql table