为什么在Neo4j中隐藏方面不好?

问题描述 投票:2回答:1

我正在尝试理解构建neo4j实体的最佳实践,考虑下面文章中提到的关于隐藏https://neo4j.com/blog/dark-side-neo4j-worst-practices/的方面的最佳实践

下图说明当“country”属性被建模为与Person节点的关系而不是将其包含在节点本身中时,性能会更好

当它被建模为查询的单独实体时,重点在于性能改进,该查询使得居住在特定国家的人们。

https://s3.amazonaws.com/dev.assets.neo4j.com/wp-content/uploads/20160223191647/neo4j-data-modeling-hide-concepts.png

情况1:“country”字段在Person Entity中,因此查询遍历两个节点以检查country字段是否相同

案例2:“国家”作为一个单独的实体。

我无法理解案例2中的检查数量是多少。请帮我 。非常感谢你的时间

neo4j spring-data-neo4j
1个回答
2
投票

这里有一些事情会影响你的建模决策。

首先,当我们从一个字段值中提取出一个节点时,我们正在对数据进行规范化。而不是为所有人复制相同的值(例如,“UK”):居住在英国的人员节点,我们现在只有一个:具有“UK”代码的Country节点,以及居住在那里的所有人员节点:LIVES_IN与其国家/地区节点的关系。所以在这方面,我们避免重复数据库中的字符串数据。

另一件需要考虑的事情是,在Neo4j中,属性查找和过滤通常是更昂贵的操作之一,因此通常可以通过调整查询和建模来优化,以最大限度地减少属性查找和属性过滤。

对于第一种情况,我们总是要过滤所有朋友以获取所需国家/地区的朋友。虽然这对于这样一个小型数据集(一个人的朋友)来说不会有问题,但对于更复杂的查询,您可能会进行大量的属性查找和过滤,这可能会减慢查询执行速度。

在第二种情况下,除了查找Stefan节点之外,规划人员可以通过索引查找(在:国家(代码))上匹配国家进行优化(如果规划人员不这样做,我们可以使用计划员提示强制它)。在英国国家节点预先匹配的情况下,我们可以将模式扩展到朋友及其国家/地区节点,这将对英国节点(或节点散列连接,取决于规划者的方法)执行ExpandInto操作。在任何一种情况下,过滤操作根本不需要进行属性访问,而是基于我们预先匹配的UK节点(基于节点的图标id的底层过滤器)进行过滤,这是一种有效的操作。

您可以使用PROFILE或EXPLAIN来检查计划程序将如何执行查询。

与性能无直接关系的另一个方面是在提取出类似实体时解锁的灵活性和实用性,而不是将它们保留为属性字段。

通过将国家/地区提取到自己的节点,我们现在可以在不同的上下文中使用这些节点。虽然我们目前有:LIVED_IN关系:Person和:Country节点,我们现在可以添加任何其他类型的关系:Country节点。我们可以在图中获得这样的数据:

(:Person)-[:TRAVELED_TO]->(:Country)
(:Language)-[:COMMONLY_SPOKEN_IN]->(:Country)
(:State)-[:LOCATED_IN]->(:Country)

和更多。虽然我们可以自己使用这些模式,但是当我们需要将多个部分包含在同一模式中时,真正的力量就会出现,这样我们就可以在查询时拥有丰富的上下文。

例如:“我想知道我的哪些朋友居住或前往一个普遍使用西班牙语的国家,然后回到朋友和匹配的国家”

MATCH (me:Person {name:'InverseFalcon'})-[:FRIENDS_WITH]->(friend)-[:LIVES_IN | TRAVELED_TO]->(country:Country)<-[:COMMONLY_SPOKEN_IN]-(:Language {name:'Spanish'})
RETURN friend, collect(country.code) as countries

通过像这样重构我们的模型,我们避免了提取属性值的笨拙,并且必须在后续匹配中使用它们(类似于表连接)。

© www.soinside.com 2019 - 2024. All rights reserved.