google-app-engine - 有什么策略可以评估数据存储模型的 TextProperty 中保存的数据压缩所带来的 CPU 损失和内存增益之间的权衡?

标签 google-app-engine google-cloud-datastore

非常大的 TextProperties 会成为负担吗?它们应该被压缩吗?

假设我有一个信息存储在我的数据存储实体中的 2 个 TextProperty 类型的属性中。 这些字符串的长度始终相同,均为 65,000 个字符,并且具有大量重复整数,示例如下:

entity.pixel_idx   = 0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5....etc.
entity.pixel_color = 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,...etc.

因此,上面的这些也可以使用更少的存储空间来表示,方法是仅使用每个整数及其序列的长度进行压缩('0,8' 表示 '0,0,0,0,0,0 ,0,0') 但是压缩和解压缩需要时间和 CPU 吗? 有什么一般想法吗? 是否有一些技巧可以测试解决问题的不同尝试?

最佳答案

如果所有整数都是单位数(如示例中所示),那么只需省略逗号即可将存储空间减少一半。

简短回答

如果您期望有大量重复,那么压缩您的数据是有意义的 - 您的数据不是那么小(65K)并且高度重复 => 它将很好地压缩。这将节省您的存储空间,并减少查询数据时从数据存储区传回数据所需的时间。

长答案

我从您提供的简短示例字符串开始进行了一些测试,并且该字符串重复了 65000 个字符(可能比您的实际数据重复更多)。该字符串从 65K 压缩到几百字节;您可能需要根据数据的实际压缩程度进行一些额外的测试。

无论如何,测试显示使用压缩数据与未压缩数据相比可以节省大量成本(对于上述测试,压缩效果非常好!)。特别是对于压缩数据:

  • 单个实体的 API 时间缩短了 10 倍(平均为 41 毫秒,而平均为 387 毫秒)
  • 使用的存储空间显着减少(因此 GAE 似乎没有对您的数据进行任何压缩)。
  • 出乎意料的是,CPU 时间减少了约 50%(提取 100 个实体时为 130 毫秒,而提取 100 个实体时为 180 毫秒)。我预计 CPU 时间会更糟,因为必须解压缩压缩数据。必须有一些其他 CPU 工作(例如解码 Protocol Buffer ),对于更大的未压缩数据,这甚至需要更多的 CPU 工作。
  • 这些差异意味着压缩版本的挂钟时间也显着加快(提取 100 个实体时为 426 毫秒,而 <100 毫秒)。

为了更轻松地利用压缩,我编写了一个自定义 CompressedDataProperty它处理所有的压缩/解压缩业务,因此您不必担心它(我也在上面的测试中使用了它)。您可以从上面的链接获取源代码,但自从我为此答案编写它以来,我也将其包含在此处:

from google.appengine.ext import db
import zlib
class CompressedDataProperty(db.Property):
  """A property for storing compressed data or text.

  Example usage:

  >>> class CompressedDataModel(db.Model):
  ...   ct = CompressedDataProperty()

  You create a compressed data property, simply specifying the data or text:

  >>> model = CompressedDataModel(ct='example uses text too short to compress well')
  >>> model.ct
  'example uses text too short to compress well'
  >>> model.ct = 'green'
  >>> model.ct
  'green'
  >>> model.put() # doctest: +ELLIPSIS
  datastore_types.Key.from_path(u'CompressedDataModel', ...)

  >>> model2 = CompressedDataModel.all().get()
  >>> model2.ct
  'green'

  Compressed data is not indexed and therefore cannot be filtered on:

  >>> CompressedDataModel.gql("WHERE v = :1", 'green').count()
  0
  """
  data_type = db.Blob

  def __init__(self, level=6, *args, **kwargs):
    """Constructor.

    Args:
    level: Controls the level of zlib's compression (between 1 and 9).
    """
    super(CompressedDataProperty, self).__init__(*args, **kwargs)
    self.level = level

  def get_value_for_datastore(self, model_instance):
    value = self.__get__(model_instance, model_instance.__class__)
    if value is not None:
      return db.Blob(zlib.compress(value, self.level))

  def make_value_from_datastore(self, value):
    if value is not None:
      return zlib.decompress(value)

关于google-app-engine - 有什么策略可以评估数据存储模型的 TextProperty 中保存的数据压缩所带来的 CPU 损失和内存增益之间的权衡?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2582799/

相关文章:

java - 谷歌应用引擎如何处理图像数据?如何操作像素数据?

java - 我可以在 Google App Engine 上使用 Tika 进行内容提取吗?

java - Appengine 模块dispatch.xml 路由与自定义域

java - 无法运行示例 "BookShelf"Java App Engine 应用程序

java - Google App Engine 的可分发应用程序

python - 坏值错误 : Indexed value message_text must be at most 1500 bytes

java - 在静态字段中缓存 DatastoreService 对象是否安全? (GAE Java)

java - 创建搜索索引 GAE 地理空间查询的权限被拒绝

sql - Google数据存储区Nosql和Google bigquery sql之间的实际区别是什么?

python - 启动、停止和继续 Google App Engine BulkLoader