Database 在数据库中存储有序列表(间隙方法)

Database 在数据库中存储有序列表(间隙方法),database,google-app-engine,list,google-cloud-datastore,Database,Google App Engine,List,Google Cloud Datastore,我想在Google App Engine数据存储中保留一个大的有序列表(数百万个元素)。需要快速插入 最简单的方法是添加表示顺序的索引属性(或列)“order_num”。例如,列表[a,B,C]将按如下方式存储: content order_num -------------------- A 1 B 2 C 3 value (PK) predecessor ------------------------ A

我想在Google App Engine数据存储中保留一个大的有序列表(数百万个元素)。需要快速插入

最简单的方法是添加表示顺序的索引属性(或列)“order_num”。例如,列表[a,B,C]将按如下方式存储:

content   order_num
--------------------
   A         1
   B         2
   C         3  
value (PK)   predecessor
------------------------
  A              null
  B               A
  C               B
但是,这并不能让您快速插入。例如,如果我想在A之后插入X,我必须重新编号B和C为X“腾出空间”,也就是说,让B变成3,C变成4,X变成2。如果我有数百万的元素,这将是一场灾难

我找到了一个可行的解决方案,称为“差距法”。这种方法在相邻元素之间保持间隙。像这样:

content   order_num
--------------------
   A         1000
   B         2000
   C         3000
当我想在A之后插入X时,我可以简单地添加X,其order_num设置为(1000+2000)/2=1500,无需重新编号

但随着这些差距越来越小,可能需要重新编号。我的问题是,是否有任何已知的重新编号策略?决定差距的大小

谢谢

更新

这里有更多的细节。假设我在数据库中有一个元素列表,每个元素都有一个名为my_num的整数属性。my_num的值是任意正整数。假设我有一个列表[a,B,C,D],它们的my_num是

 element    my_num   
---------------------
   A          5        
   B          2
   C         10
   D          7
现在,让我们定义一个accum()运算符:

accum(n) = element[0].my_num + element[1].my_num + ... + element[n-1].my_num
因此,每个元素的累积值为

 element    my_num   accum 
----------------------------
   A          5        5
   B          2        7
   C         10       17
   D          7       24
但accum值可能不应该存储在数据库中,因为列表会不断更新。最好保持快速插入

我想设计一个输入为整数x的查询:

query(x) = element[i] if accum(i-1) < x <= accum(i)

query(x)=元素[i]如果acum(i-1)
content     order
-------------------- 
   A         'a' 
   B         'b' 
   C         'c'
然后在a和b之间插入D,给它一个值“aa”

生成字符串的算法最适合二进制字符串:如果要在“1011”和“1100”之间插入内容,请执行以下操作:

  • Avalue=1+0*(1/2)+1*(1/4)+1*(1/8)
  • b值=1+1*(1/2)+0*(1/4)+0*(1/8)
平均值,新值=1+0*(1/2)+1*(1/4)+1*(1/8)+1*(1/16) 新字符串=“10111”

由于始终平均2个值,因此平均值将始终具有有限的二进制开发和有限的字符串。它有效地定义了二叉树

正如您所知,二叉树并不总是能够很好地平衡,换句话说,在插入足够多的字符串后,某些字符串将比其他字符串长得多。为了保持它们的简短,你可以使用任何偶数基-它必须是偶数,因为两个值的任何平均值的发展都是有限的

但是无论您做什么,字符串都可能变长,并且您必须在某个时候进行一些整理,清理值,以便有效地使用字符串空间。这个算法给你的是,在两次清理之间,系统肯定会继续运转。

你可以创造一个巨大的。。。。每个实体都指向列表中的下一个实体

稍后遍历列表的速度会非常慢,但这可能是可以接受的,具体取决于您使用数据的方式,并且在列表中插入的数据存储将只有两次写入(一次用于更新插入点,另一次用于新实体)

在数据库中,可以按如下方式创建链接列表:

content   order_num
--------------------
   A         1
   B         2
   C         3  
value (PK)   predecessor
------------------------
  A              null
  B               A
  C               B
然后,在插入新数据时,更改前置数据:

value (PK)   predecessor
------------------------
  A              null
  B               A
  C               D
  D               B

插入很快,但遍历确实会很慢

> P>您可能想考虑使用,它使用基于树的结构来维护数据存储中的秩顺序。


或者,如果您可以更详细地描述您的需求,也许我们可以建议一种开销更小的替代方案。

浮点数也有限制。你不能无限地拆分小数。使用字符串作为索引解决了这个问题,但随着元素数量的增加,字符串会变得更长。长字符串可能会导致性能下降和浪费磁盘空间。@eliang,关于浪费磁盘空间的担忧可能不是反对这一点的好论据。使用“间隙法”时,如果您的数据足够密集,不会浪费大量空间存储零,那么您可能无法从使用间隙中获得全部好处(感觉您可能会在所有数据上运行,并经常添加另一个零)。@Robert您说得对。如果我使用字符串方法,是否有任何已知的策略来生成这些顺序字符串?谢谢@eliang,编辑我的答案,给出这样一个策略。如果你想挑选在该领域更有经验的人的大脑,也许应该重新标记数据结构算法之类的问题。。。500个字符是App Engine上索引字符字段的最大长度。除此之外,您必须使用文本字段,但它们不能被索引。。。因此,在大量插入之后,这种方法可能会受到严格限制。我没有更好的了!你也需要好的阅读性能吗?您是打算稍后在后台处理此列表,还是需要将列表的各个部分快速返回给用户?此列表用于后台处理。是否没有可用于定义顺序的数据?如果它取决于时间、价格、启发值,你可以插入吗?@boisvert不,这就是为什么我感到困惑。你在你的项目中实现了@boisvert的解决方案吗?你能详细介绍一下你的最终实现吗?我想到了这个方法。但是它在遍历列表时使用了太多的磁盘访问。列表将按元素处理,因此我认为最好一次获取多个元素以减少磁盘访问。我花了一些时间研究它。伟大的解决方案排名问题。它提供从分数到排名的快速查询,反之亦然。但我想要的是一种不同的查询,我在原来的帖子中添加了这种查询。谢谢@eliang您可以根据自己的需要调整ranklist基于树的方法。或者,如果您的数据集很小,请按照您的描述在运行时累积结果。或者,如果结果很大但不经常更新,则在写入时更新结果并将其存储到peris