关于嵌套vs父/子文档的缩放

Der*_*gan 12 elasticsearch

我正在为我们运行概念验证,以便在ES中对更"标准化"的数据运行嵌套查询.

例如,嵌套

客户 - > - 名称
- 电子邮件 - 事件 - > - 创建 - 类型

现在我的情况是,给定客户的事件列表可以移动到另一个客户.例如,客户A有50个事件,客户B有5000个事件

我现在想将所有事件从客户A转移到客户B

对于数百万客户和规模运行,在UI上运行图表是父/子更合适还是应该嵌套能够处理它?

我的情况有哪些优点和缺点?

Zac*_*ach 22

很难给你甚至粗略的性能指标,如"嵌套足够好",但我可以给你一些关于嵌套vs父/子的详细信息,可以提供帮助.我仍然建议进行一些基准测试来验证性能是否可以接受.

嵌套

  • 嵌套文档彼此存储在相同的Lucene块中,这有助于读取/查询性能.读取嵌套文档比等效父/子快.
  • 更新嵌套文档(父级或嵌套子级)中的单个字段会强制ES重新索引整个嵌套文档.对于大型嵌套文档,这可能非常昂贵
  • 更改"父"意味着ES将:删除旧文档,使用较少嵌套数据重新索引旧文档,删除新文档,使用新嵌套数据重新索引新文档.

父/子

  • 子项与父项分开存储,但路由到同一个分片.因此,父/子在读/查询上的性能略低于嵌套
  • 父/子映射有一点额外的内存开销,因为ES在内存中维护一个"连接"列表
  • 更新子doc不会影响父级或任何其他子级,这可能会在大型文档上节省大量索引
  • 更改父级意味着您将删除旧的子文档,然后在新父级下索引相同的doc.

Nested可能会正常工作,但如果你认为有很多"数据改组"的可能性,那么父/子可能更适合.嵌套最适合嵌套数据不经常更新但经常读取的情况.对于数据更频繁移动的安排,父/子更好.

  • 这仅适用于界面(例如,允许最终用户更新字段而不提供整个文档).在内部,Lucene从_source(必须存储)发出删除然后重新索引.Lucene只在初始文档创建期间编写连续的块,从不随机访问写入,因此更新根本不可能.甚至删除实际上都没有被删除,只是标记为已删除,直到下一次合并清除它们为止. (5认同)