非常大的 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/