Sql 如何在数据库中存储经常改变位置的订购项

Sql 如何在数据库中存储经常改变位置的订购项,sql,data-structures,recursion,indexing,linked-list,Sql,Data Structures,Recursion,Indexing,Linked List,我需要能够在数据库中存储一个大的有序项目列表。到目前为止,这是直截了当的: ID Position OtherFields 1 45 ... 2 4736 ... 3 514 ... ... 在查询中,我总是需要只获取几个项目(根据其他字段过滤),但顺序正确。同样简单,在位置上放置索引并使用“按位置排序” 现在问题来了:物品的位置经常改变,而不仅仅是1或2。如果ID2将位置从4736更改为2000,则需要更新其位置以及旧位置2000和47

我需要能够在数据库中存储一个大的有序项目列表。到目前为止,这是直截了当的:

ID Position OtherFields
 1     45      ...
 2   4736      ...
 3    514      ...
 ...
在查询中,我总是需要只获取几个项目(根据其他字段过滤),但顺序正确。同样简单,在位置上放置索引并使用“按位置排序”

现在问题来了:物品的位置经常改变,而不仅仅是1或2。如果ID2将位置从4736更改为2000,则需要更新其位置以及旧位置2000和4735之间所有元素的位置,每行添加1。而且,每个事务都会改变的不仅仅是一个ID,还有一些ID,而且在短时间内可能会有很多事务

我认为处理更新问题的最优雅的方法是使用链表而不是位置列,在这里我可以通过将ID2的前一个链接到后一个链接将其从原来的位置删除,然后通过将其链接到新的前一个和后一个链接将其插入其他位置。这将是一个恒定的和少量的更新每个位置的变化,这也是我处理变化的首选方式(在我的例子中是Java)。然而,这就产生了按正确顺序查询的N+1问题-即使是少数元素,我也必须在最坏的情况下浏览整个列表,以找出它们的正确顺序

所以我的问题是:为了在必要的更新和查询性能之间取得良好的平衡,您有什么建议

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

  • 是否有一个DBMS(理想情况下是开源的)可以处理链表,不仅具有语法上的糖分,而且还具有良好的性能,例如通过使用链接元素的内部索引

  • 也许这也是一个选择,只是有一个BLOB,整个链表将存储在其中!这样一个链表能有多大/它在数据库中会使用多少内存,以及当为1.000.000个条目获取时会使用多少内存?我正在使用Java+Hibernate,以防万一。我认为在获取BLOB之后,即使是在内存中处理整个列表也应该非常快


  • 当然,也欢迎其他想法

    如果您放宽了
    位置
    列必须包含从1到N的整数的限制,而是允许它包含任何数字,那么您可以高效地执行搜索和更新


    通过计算平均值(A+B)DIV 2,可以在位置为A和B的其他两个项目之间插入一个项目。例如,如果A是10000,B是12000,那么您的新职位是11000。有时,由于集群的原因,您可能会用完间隙,此时您可以在整个表中运行,以便更均匀地重新分配位置。

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


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

    原始记录如下:

    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的建议后,我们的解决方案似乎非常相似,尽管对我来说使用十进制似乎更简单…

    另一个解决方案是使用词汇排序。每当两个字符串之间没有值时,只需添加一个新字符。唯一的缺点是,与其他答案中提到的数值解相比,它消耗更多的内存

    对于无错误的数据库,规范化不是必需的,但是可以选择进行规范化以减少字符串长度


    这里有一个有趣的视频,详细解释了这一点:

    比尔·卡温对此有一个很好的答案,你可能想看看:我认为比尔的“树”解决方案不合适。虽然数据是分层的,但它是一个单一的、大的树路径,每次插入后都必须更新,这相当于重新编制索引。我也读过这个问题,起初我觉得它很有希望,但后来我意识到,例如,对于2000年第1000位的条目,您必须在闭包表中创建1000个子项。总的来说,我认为这将为2000个职位提供大约2000.000.000条条目,并进行大量必要的更新-对于一个简单的列表来说,在写作方面的工作和表现太多了,所以我同意Marcus的观点。在软件工程网站上也有类似的情况:我只是把它扔了出去。位置可以是浮动列吗?你总是可以把一个数字分成两半。:)@马库斯·亚当斯:可以,但你最终还是会遇到同样的问题,即由于精度和舍入误差而没有间隙。不管怎么说,考虑这个问题很有趣。这完全有道理,我想我会尝试使用BIGINT。只要读一读未签名的,它从0到18.446.744.073.709.551.615。即使从1.000.000个平均分布的条目列表开始,这也会留下大约。。。18.446.744.073.709中间的条目,在第一次碰撞之前留出一段时间。在最坏的情况下(所有更新总是进入最小的间隙,总是被分成2),我认为在必要的重新分配之前应该是44次更新(2^44=17.592.186.044.416<18.446.744.073.709)。平均值是一个聪明的举动!不幸的是,当你重做发行版时……你发明了杜威十进制。这最好作为一个评论,而不是一个答案。