在 JSON 中存储嵌套数据还是使用具有唯一名称的平面结构更好?

rea*_*dul 7 json nosql elasticsearch amazon-dynamodb

简单来说:是

{
    "diary":{
        "number":100,
        "year":2006
    },
    "case":{
        "number":12345,
        "year":2006
    }
}
Run Code Online (Sandbox Code Playgroud)

或者

{
    "diary_number":100,
    "diary_year":2006,
    "case_number":12345,
    "case_year":2006

}
Run Code Online (Sandbox Code Playgroud)

使用 Elasticsearch 时更好?

在我的情况下,总键只有几个(10-15)。哪个更好的性能明智?

用例是显示来自 noSQL 数据库(主要是 dynamoDB)的数据。还将其输入 Elasticsearch。

Pol*_*ton 6

我的经验法则 - 如果您需要查询/更新嵌套字段,请使用平面结构。

如果您使用嵌套结构,则弹性将使其扁平化,但会产生管理这些关系的开销。性能明智 - 扁平化总是更好,因为弹性不需要关联和查找嵌套文档。

以下是管理 Elasticsearch 内部关系的摘录,其中列出了您可能需要考虑的一些缺点。

Elasticsearch 从根本上来说仍然是扁平的,但它在内部管理嵌套关系以提供嵌套层次结构的外观。当您创建嵌套文档时,Elasticsearch 实际上索引两个单独的文档(根对象和嵌套对象),然后在内部关联这两个文档。两个文档都存储在同一个 Shard 上的同一个 Lucene 块中,因此读取性能仍然非常快。

这种安排确实有一些缺点。最明显的是,您只能使用特殊的nested query. 当您需要更新文档(根或任何对象)时,就会出现另一个很大的缺点。

由于文档都存储在同一个 Lucene 块中,并且 Lucene 不允许对其段进行随机写入访问,因此更新嵌套文档中的一个字段将强制重新索引整个文档。

这包括根和任何其他嵌套对象,即使它们没有被修改。在内部,ES 会将旧文档标记为已删除,更新字段,然后将所有内容重新索引到新的 Lucene 块中。如果您的数据经常更改,嵌套文档可能会产生与重新索引相关的不可忽略的开销。

最后,嵌套文档之间不可能“交叉引用”。一个嵌套文档无法“看到”另一个嵌套文档的属性。例如,您不能过滤“A.name”,但过滤“B.age”的方面。你可以通过使用来解决这个问题include_in_root,它有效地将嵌套的文档复制到根目录中,但这会让你回到内部对象的问题。