原文地址: https://www.elastic.co/guide/cn/elasticsearch/guide/current/parent-child-performance.html, 版权归 www.elastic.co 所有
英文版地址: https://www.elastic.co/guide/en/elasticsearch/guide/current/parent-child-performance.html
英文版地址: https://www.elastic.co/guide/en/elasticsearch/guide/current/parent-child-performance.html
请注意:
本书基于 Elasticsearch 2.x 版本,有些内容可能已经过时。
本书基于 Elasticsearch 2.x 版本,有些内容可能已经过时。
实际使用中的一些建议edit
当文档索引性能远比查询性能重要的时候,父-子关系是非常有用的,但是它也是有巨大代价的:父-子查询速度会比等效的嵌套查询慢5到10倍!
全局序号和延迟 (Global Ordinals and Latency)edit
父子关系使用了全局序号来加速文档间的联合。不管父子关系映射是否使用了内存缓存或基于硬盘的doc values
,当索引变更时,全局序号要重建。
一个分片中父文档越多,那么全局序号的重建就需要更多的时间。父子关系更适合于父文档少、子文档多的情况。
全局序号默认情况下是延迟构建的:在refresh
后的第一个父子查询会触发全局序号的构建。而这个构建会导致用户使用时感受到明显的延迟。你可以使用全局序号预加载(Eager global ordinals)来将全局序号构建的开销由查询阶段转移到refresh
阶段,通过如下方式映射_parent
字段:
PUT /company { "mappings": { "branch": {}, "employee": { "_parent": { "type": "branch", "fielddata": { "loading": "eager_global_ordinals" } } } } }
当父文档过多时,全局序号的构建可能需要几秒钟时间。在这种情况下,增加refresh_interval
是有意义的,这样刷新(refresh)的次数就少了,全局序号的有效期也就更长了。这将大大降低每秒重建全局序号的cpu消耗。
多代(Multigenerations)和结束语edit
多代文档的关联查询(查看祖辈与孙辈关系)虽然看起来很吸引人,但必须考虑如下的代价:
- 关联越多,性能越差。
-
每一代的父文档都要将其字符串类型的
_id
字段存储在内存中,这会占用大量内存。
当你考虑父子关系是否适合你现有关系模型时,请考虑下面这些建议:
- 尽量少地使用父子关系,仅在子文档远多于父文档时使用。
- 避免在单个查询中使用多个父子关联语句。
-
避免在
has_child
过滤中计算得分,通过设置has_child
查询的score_mode
为none
不再计算得分。
(原文: Avoid scoring by using the has_child filter, or the has_child query with score_mode set to none.) - 保证父 ID 尽量短,以便在 doc values 中更好地压缩,被临时载入时占用更少的内存。
最重要的是: 考虑一下我们在接触父-子关系之前讨论过的其他关系。