在App-Engine中存储元组列表的最佳性能方式是什么?

10 投票
1 回答
2705 浏览
提问于 2025-04-16 12:05

在存储和获取一个包含元组列表的数据实体时,最有效的存储方式是什么呢?

我遇到过这个问题,元组可以是键值对、日期时间和样本结果,或者是 (x, y) 坐标。
元组的数量是可变的,从1个到几百个都有。

包含这些元组的实体需要能够快速且便宜地被引用,而元组的值不需要被索引。

我遇到过这个问题几次,并用不同的方法解决过。

方法1:

把元组的值转换成字符串,并用某种分隔符把它们连接在一起。

def PutEntity(entity, tuples):
  entity.tuples = ['_'.join(tuple) for tuple in tuples]
  entity.put()

优点:在数据存储查看器中结果易于阅读,所有数据一次性获取。
缺点:可能会丢失精度,程序员需要进行反序列化/序列化,存储字符串格式的数据需要更多的字节。

方法2:

把每个元组的值存储在一个列表中,并对元组进行压缩/解压。

def PutEntity(entity, tuples):
  entity.keys = [tuple[0] for tuple in tuples]
  entity.values = [tuple[1] for tuple in tuples]
  entity.put()

优点:没有精度损失,虽然有点复杂但仍然可以在数据存储查看器中查看数据,可以强制类型,所有数据一次性获取。
缺点:程序员需要压缩/解压元组,或者小心维护列表中的顺序。

方法3:

以某种方式(比如json、pickle、协议缓冲区)序列化元组列表,并将其存储在一个二进制大对象或文本属性中。

优点:可以与对象和更复杂的对象一起使用,减少了元组值不匹配的错误风险。
缺点:访问二进制大对象需要额外的获取?无法在数据存储查看器中查看数据。

方法4:

把元组存储在另一个实体中,并保留一个键的列表。

优点:架构更清晰。如果这个实体是一个视图,我们就不需要保留两份元组数据。
缺点:需要两次获取,一次获取实体和键列表,一次获取元组。

我想知道有没有人知道哪种方法性能最好,或者有没有我没想到的其他方法?

谢谢,
吉姆

1 个回答

5

我使用的是方法三。Blobstore 可能需要额外的获取操作,但 db.BlobProperty 就不需要。对于那些需要确保从存储中取出时和放入时完全一样的对象,我使用 PickleProperty(可以在 tipfy 和一些其他工具库中找到)。

对于那些我只需要保存状态的对象,我写了一个 JsonProperty 函数,它的工作方式类似于 PickleProperty(但显然是使用 SimpleJson)。

对我来说,能够一次性获取所有数据,并且确保操作简单易懂,比 CPU 性能更重要(在 App Engine 上)。根据 Google I/O 关于 AppStats 的讲座,访问数据存储几乎总是比一些本地解析要贵。

撰写回答