1

我想标题说明了一切,但让我详细说明一下:

基本上,如果我将(均匀分布的)8 位数据存储到 AppEngine 数据存储中,我是否可以期望在我的 1 字节中使用 1 字节的存储空间byte[],或者是否存在一些编码开销,例如 50% 的开销,如果它是 UTF-8 编码的(因为值 128..255 占用 2 个字节)?

在文档中它说:

BlobProperty - Uninterpreted byte string

不确定这是否意味着 8 位字节(未解释的字节)或者这是否意味着某种编码(字符串)......

setStringValueAsBytes(...)不幸的是,我在PropertyValue课堂上找不到 - 方法的源代码。大概就是答案了……

PS:这个问题可能与您使用的是 Python、Java、Go 还是 PHP 无关,但万一这很重要:我使用的是 Java API。

4

2 回答 2

2

该信息并未完全公开,但 Google 已经提到 HRD 是建立在 BigTable 之上的,而且我们也知道 Google 内部并没有真正使用 BigTable,而是使用了 Megastore,这是一个更高级的开发。

现在我们并不确切知道 HRD 运行在什么上,但我认为如果您阅读 BigTable 和 Megastore 的工作原理,您可能会得到一个不错的主意。

http://research.google.com/archive/bigtable.html

http://research.google.com/pubs/pub36971.html

现在回答您的问题,我不知道您为什么认为 Google 会将二进制数据存储为 UTF-8。一开始这是一个迟钝的想法,如果谷歌以这种方式实施它,那将是相当迟钝的。所以我非常怀疑他们会这样做。

更实际地,大多数数据存储系统都具有分配给任何数据块的最小块大小。BigTable 白皮书提到它是可配置的,但默认为 64KB。我们不知道 HRD 是否使用此默认值或其他调整值。

无论如何,我认为您不应该担心您的二进制数据被存储为 UTF-8。这是极不可能的。但是,您的数据很可能会占用一些最小块大小。请记住,您的实体与其属性名称一起存储,因此会有开销。但很可能您的开销将是您的实体被压缩到最小的块大小,而不是任何 UTF-8 担忧。担心您的属性名称可能会以 UTF-8 存储是很现实的,因此我会避免在属性名称中使用扩展字符。

于 2013-08-15T04:57:36.710 回答
1

最后更新:

我有一些时间来实际测试这一点,首先创建 1024 个实体,每个实体都有一个包含 100KB 随机 8 位数据的 Blob 属性,等待五天让所有统计信息在 AppEngine 控制台中更新,然后替换属性每个实体上都有 200KB 的随机 8 位数据。Quota DetailsDatastore Stored Data的差异和Datastore StatisticsTotal Size的差异正好是 100MB,因此没有开销。如果数据采用 UTF-8 编码,则差异为 150MB。

所以答案是:

AppEngine 数据存储区将 8 位二进制数据存储为没有编码的纯 8 位字节。

好的...

附注:配额中Datastore Stored Data的“1 GByte”对应于 1024 3个字节(GB 的原始定义,现在通常称为 GiB),而不是 10 9(Giga 的公制解释)。耶!为我们的钱增加 7.3% 的存储空间!这就是为什么我比西部数据更喜欢谷歌...... :)

原始答案:

我终于找到了一些稀疏的文档来阐明这个问题:

数据存储区定义了一组它支持的数据类型:str、int32、int64、double 和 bool

这部分文档指出“[i]在内部,所有str值都是 UTF-8 编码并按 UTF-8 代码点排序”。1

现在, Types and Property Classes的 Python 2文档将Blob类定义为“内置str类型的子类”,并说“此值存储为字节字符串,编码为文本”。

虽然这远不是​​ 100% 清楚的(“未编码为文本”真的意味着“未编码为 UTF-8”吗?),但似乎表明数据在物理保存时确实保留为数据存储中的 8 位字节。

与其说这是一个比@dragonx 更好的答案,我会将此作为进一步证明他是正确的证据,特别是因为我完全同意他的说法,即“[这将是] 一开始是一个迟钝的想法,它会谷歌以这种方式实施它是相当迟钝的”

也许有一天我会做一个实际的测试。在那之前,我希望谷歌确实没有被削弱。数据存储中任何二进制数据的 50% 存储成本开销应该足以让他们尝试避免......

旁白:

1这就是为什么我首先担心这个话题。

2这可能是我错过此信息的原因。等效的Java 文档并没有真正提到这一点。

更新:

找到了更多的支持证据:

在“属性”部分末尾的“实体表”部分中途,它说:

“在内部,App Engine 将实体存储在协议缓冲区中,这是序列化结构化数据的有效机制;有关更多详细信息,请参阅开源项目页面。”

开源项目包含一个名为CodedOutputStream.java的文件(我认为)它负责实际组装构成存储协议缓冲区的二进制数据。它定义了两个方法:writeString(...)writeByteArray(...),它们都调用各自的write...NoTag(...)方法。

我们writeStringNoTag(...)终于找到了对字符串进行 UTF-8 编码的行:

final byte[] bytes = value.getBytes("UTF-8");

此行在 中不存在writeByteArrayNoTag(...)

认为这意味着以下几点:

  • 当我存储一个 Blob 时,它最终会使用该writeByteArray(...)方法,因为我看不出它存在的其他原因,并且Blob 类在内部将其数据存储在 byte[] 而不是 String 中。

    => 所以这里没有编码...

  • 由于writeStringNoTag(...)对字符串执行 UTF-8 编码,任何编码都可能由协议缓冲区库完成。

    => 所以以后也没有进一步的编码......

现在,这是否足以与“[i] 在内部,所有 str值都是 UTF-8 编码”和“二进制数据 [...] 是内置str类型的子类”相矛盾,这明确暗示二进制数据也是UTF-8编码的吗?

我认同...

于 2014-09-24T19:13:59.253 回答