请注意,这是我们正在为 4.0 考虑的事情。
RavenDB 原生使用 JSON 来处理几乎所有的事情。这对 JSON 文档数据库有意义。 JSON 易于解析、人类可读,并且在大多数情况下,没有真正的复杂性。
然而,虽然 JSON 易于解析,但解析它会产生一些计算开销。事实上,在我们的性能测试中,我们花了很多时间来序列化和反序列化 JSON。这是我们必须处理的主要成本之一,主要是因为这是经常发生的事情。我们以前使用 BSON 在内部存储文档,但分析实际上表明,将数据保存为 JSON 文本并对其进行解析的成本更低。这就是我们目前正在做的事情。
然而,更快的解析仍然是解析,这是我们想要避免的。这在内存中的实际表示方式也存在问题。让我们考虑以下 JSON:
{"FirstName":"John","LastName":"Smith"}
在内存中,这表示为(高度简化):
- Dictionary<string,object> 实例
- 键的字符串[]
- “名字”字符串
- “姓氏”字符串
- “约翰”字符串
- “史密斯”字符串
换句话说,特别是对于大文档,有 很多 正在创建的小对象。这不会影响即时解析成本,但确实需要在事后收集这些成本,这 是 我们希望避免的事情。
我们目前正在考虑使用 Flat Buffers 进行内部文档存储。 Flat Buffers 的好处是没有中间解析步骤。您将获得一块可以立即访问的内存。这有两个主要优点,将文档加载到内存意味着只需从磁盘读取缓冲区,无需额外成本。但这也意味着释放文档的行为会便宜得多,我们只需要再次收集缓冲区,而不是潜在的数万个小对象。
另一个好处是我们通常需要加载要索引的文档,而通常索引只需要文档中很少的字段。通过避免解析成本,只为我们实际接触的对象付出代价,我们可以更好地降低索引成本。
使用平面缓冲区的粗略模式是:
{"FirstName":"John","LastName":"Smith"}
文档中的值按字段名称排序,因此我们可以使用二进制搜索来搜索字段。
Nitpicker 角落:是的,我们可能想在这里使用哈希,但这是一个粗略的草稿来测试东西,稍后会出现。
我们需要优化模式,使用它 不会 很有趣,但速度和内存的改进应该是显着的。
另一种选择是这样的模式:
{"FirstName":"John","LastName":"Smith"}
这里我们将所有字段名称存储一次,然后我们使用其在根对象中的索引来引用字段名称。这应该具有减少重复字符串名称的优点。