Spring "supernode" 个实体上的数据 Neo4j 内存消耗
Spring Data Neo4j memory consumption on "supernode" entities
据我所知,一旦加载了 Spring Data Neo4j 中的 NodeEntity,默认行为是通过仅获取相关节点的 ID 来延迟加载其关系。
虽然在大多数情况下看起来还不错,但在所谓的 "supernodes" 的情况下我对此表示怀疑 - 与其他节点有很多关系的节点。那种节点,即使它们本身很小,也会保存大量的 id,使用比我们希望使用的更多的内存,并且可能不是 "lazily loaded enough" 实际上...
所以我的问题是——我该如何处理这种超级节点?
我的第一个想法是简单地从那种节点中删除所有@RelatedTo/@RelatedToVia 映射(或至少是关系类型为 "numerous" 的映射),并在对这些关系进行操作时简单地绕过 SDN需要,其他情况下使用 SDN。
好像有点意思?在这种情况下,您还有其他建议或经验吗?
我没有使用过 SDN,但我会尝试对元节点进行近似。通过这种近似,您可以构建一个结构,将关系总数拆分为元节点数(如果一个节点有 1000 个连接并且您使用 10 个元节点,则每个元节点将有 100 个连接,而 supernode 只是 4. 您可以在下图中看到图形表示:http://i.stack.imgur.com/DMQGs.png。
通过这种方式,您可以很好地控制有多少关系可以有一个节点,因此 SDN 将最大加载多少节点。
您可以在 http://neo4j.com/book-learning-neo4j/ and also in this similar post
上阅读更多相关信息
首先,您能否提供您正在使用的 SDN 版本,以便我们将问题定位到库的正确维护者。
其次,虽然我并不真正了解 SDN 的内部结构,但与其他 OGM 有过大量合作,但我对 LazyLoading 的理解与您提供的完全不同,原因很简单,延迟加载 ID 可以从某种意义上说,如果另一个进程正在删除具有这些 ID 之一的节点之一,您可能会损坏数据,这是非常有害的。
一般来说,在其他 OGM 中很常见,如果一个对象没有表示关系的注释,您只需从他的元数据和加载的节点重新创建该对象。
但是,如果它具有关系,则您将创建该对象的代理来扩展实体本身。
代理上的实体值不会在第一个实例中实例化,然后您将覆盖所有 getters 并在代理中添加用于检索相关节点的方法(因此实体管理器将是注入代理)。
所以基本上,在您调用其中一个 getter 之前,代理将是空的。
您还可以 "fine-grain" 通过创建扩展默认存储库的自定义存储库来实现此行为,从某种意义上说,您只能选择 LAZY_LOAD 一种类型的关系和 EAGER_LOAD 其他人。
albert描述的方法在某些情况下很有意义,但是在基本的 OGM 方面很难实现,你最好有一个 BehaviorComponent 来处理这个在 生命周期事件 期间为您提供,或向 getter 方法添加某种分页,我认为这现在不是 OGM 的一部分。
对于超级节点,我只是不指定超级节点实体上的关系。但仅限于相关节点。
如果您对关系感兴趣,您可以查找相关节点并关注超级节点。
或者,如果您确实需要加载数百万个关系,请使用 cypher 语句。
您也可以为此目的将许多关系放在一个单独的节点上,或者添加一个树状子结构,它也允许处理子选择。
据我所知,一旦加载了 Spring Data Neo4j 中的 NodeEntity,默认行为是通过仅获取相关节点的 ID 来延迟加载其关系。 虽然在大多数情况下看起来还不错,但在所谓的 "supernodes" 的情况下我对此表示怀疑 - 与其他节点有很多关系的节点。那种节点,即使它们本身很小,也会保存大量的 id,使用比我们希望使用的更多的内存,并且可能不是 "lazily loaded enough" 实际上...
所以我的问题是——我该如何处理这种超级节点?
我的第一个想法是简单地从那种节点中删除所有@RelatedTo/@RelatedToVia 映射(或至少是关系类型为 "numerous" 的映射),并在对这些关系进行操作时简单地绕过 SDN需要,其他情况下使用 SDN。 好像有点意思?在这种情况下,您还有其他建议或经验吗?
我没有使用过 SDN,但我会尝试对元节点进行近似。通过这种近似,您可以构建一个结构,将关系总数拆分为元节点数(如果一个节点有 1000 个连接并且您使用 10 个元节点,则每个元节点将有 100 个连接,而 supernode 只是 4. 您可以在下图中看到图形表示:http://i.stack.imgur.com/DMQGs.png。
通过这种方式,您可以很好地控制有多少关系可以有一个节点,因此 SDN 将最大加载多少节点。
您可以在 http://neo4j.com/book-learning-neo4j/ and also in this similar post
首先,您能否提供您正在使用的 SDN 版本,以便我们将问题定位到库的正确维护者。
其次,虽然我并不真正了解 SDN 的内部结构,但与其他 OGM 有过大量合作,但我对 LazyLoading 的理解与您提供的完全不同,原因很简单,延迟加载 ID 可以从某种意义上说,如果另一个进程正在删除具有这些 ID 之一的节点之一,您可能会损坏数据,这是非常有害的。
一般来说,在其他 OGM 中很常见,如果一个对象没有表示关系的注释,您只需从他的元数据和加载的节点重新创建该对象。
但是,如果它具有关系,则您将创建该对象的代理来扩展实体本身。
代理上的实体值不会在第一个实例中实例化,然后您将覆盖所有 getters 并在代理中添加用于检索相关节点的方法(因此实体管理器将是注入代理)。
所以基本上,在您调用其中一个 getter 之前,代理将是空的。
您还可以 "fine-grain" 通过创建扩展默认存储库的自定义存储库来实现此行为,从某种意义上说,您只能选择 LAZY_LOAD 一种类型的关系和 EAGER_LOAD 其他人。
albert描述的方法在某些情况下很有意义,但是在基本的 OGM 方面很难实现,你最好有一个 BehaviorComponent 来处理这个在 生命周期事件 期间为您提供,或向 getter 方法添加某种分页,我认为这现在不是 OGM 的一部分。
对于超级节点,我只是不指定超级节点实体上的关系。但仅限于相关节点。
如果您对关系感兴趣,您可以查找相关节点并关注超级节点。
或者,如果您确实需要加载数百万个关系,请使用 cypher 语句。
您也可以为此目的将许多关系放在一个单独的节点上,或者添加一个树状子结构,它也允许处理子选择。