Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database design 为什么索引节点或索引属性在图形数据库中更好?_Database Design_Neo4j_Graph Databases_Titan - Fatal编程技术网

Database design 为什么索引节点或索引属性在图形数据库中更好?

Database design 为什么索引节点或索引属性在图形数据库中更好?,database-design,neo4j,graph-databases,titan,Database Design,Neo4j,Graph Databases,Titan,我刚刚进入图形数据库,我似乎一直遇到一个问题,在使用“索引节点”还是“索引属性”来跟踪“节点类型”之类的东西时,我会做出选择。由于到目前为止我还没有实际经验,所以我没有任何信息可以作为做出决定的依据,而且这两种方法似乎同样有效 因此,问题是:两种方法之间的权衡是什么,规模(即节点数量)如何影响决策? 对于一个示例场景,让我们假设有两种类型的“东西”:用户和产品,用户节点和产品节点之间的边缘并不重要,但我们关心的是我们是否需要每个节点上的类型:用户和类型:产品属性,或者,如果我们希望每个节点的边分

我刚刚进入图形数据库,我似乎一直遇到一个问题,在使用“索引节点”还是“索引属性”来跟踪“节点类型”之类的东西时,我会做出选择。由于到目前为止我还没有实际经验,所以我没有任何信息可以作为做出决定的依据,而且这两种方法似乎同样有效

因此,问题是:两种方法之间的权衡是什么,规模(即节点数量)如何影响决策?

对于一个示例场景,让我们假设有两种类型的“东西”:
用户
产品
,用户节点和产品节点之间的边缘并不重要,但我们关心的是我们是否需要每个节点上的
类型:用户
类型:产品
属性,或者,如果我们希望每个节点的边分别指向
用户
节点和
产品
节点

在什么情况下,哪种方法更好


注意:我特别关注Neo4j和Titan,但我认为这将更普遍地应用。

您想问什么样的查询?在Neo4j中,您可以创建一个
用户
和一个
产品
索引,甚至可以将它们组合在一个索引中,然后可以询问如下问题

start bob = node:User(name='Bob') match ....
甚至全文搜索。为了方便地检查节点是用户还是产品,您可以将属性保留在节点上,以方便快速地遍历。如果您没有从用户/产品遍历到实例节点(您为此进行索引查找),您甚至可以通过将
Product
User
关系返回到类型(超级)节点来进行检查,这样您就可以像

start s = node:User(name='Bob') match s-[r]-(product)-[typeRel:PRODUCT]->() return product 

HTH

首先,您需要问问自己:顶点/节点的类型是否需要索引?也就是说,您是否需要按类型检索顶点/节点,比如说,从图中检索所有“用户”顶点,或者您是否需要回答从检索给定类型的所有顶点开始,然后进一步过滤/处理这些顶点的查询

如果这个问题的答案是“是”,那么我建议您将该类型存储为索引的字符串属性。或者,如果使用基于jvm的语言进行开发,则可以定义类型枚举并将其用作属性类型,以实现更高的类型安全性和自动错误检查。Titan支持将任意用户定义的类/枚举作为属性类型,并将压缩这些类/枚举以减少内存占用

然而,这种方法的缺点是,它无法扩展,因为您正在构建一个低选择性指数。这意味着可能会有很多“用户”或“产品”类型的顶点,所有这些顶点都需要分别与“用户”或“产品”的索引项相关联。这使得维护和查询这个索引非常昂贵,而且难以扩展(想象一下facebook有一个“类型”索引:“照片”条目下有数十亿个顶点)。如果您(还)不关心缩放,那么这是可行的

如果问题的答案是否定的,那么我建议将类型建模为图中的顶点/节点。即,从每个用户到“用户”顶点有一个“用户”顶点和一个“产品”顶点,以及一个标记为“类型”的边,等等

这种方法的优点是使用图形来建模数据,而不是让数据库之外的字符串值表示关键的类型信息。在构建应用程序时,图形数据库将成为它的中心组件,并持续很长时间。随着编程语言和开发人员的来来往往,您不希望数据建模和类型信息与之相伴,并面临这样一个问题:“特殊用户是什么意思?”相反,要有一个特殊用户顶点,并向其添加出处信息,即是谁创建了此类型,它代表什么和一个简短的描述-都在数据库中


这种方法的一个问题是,随着应用程序的扩展,“用户”和“产品”顶点上会有很多边。换句话说,您正在创建超级节点,这会产生缩放问题。这就是为什么Titan引入了单向边的概念。单向边类似于web上的链接:起始顶点指向另一个顶点,但该顶点不知道该边。由于您不希望从“用户”顶点遍历到所有用户顶点,因此除了获得可伸缩性和性能外,您没有失去任何东西。

我在这里忽略了索引的一个非常重要的原因。假设您有一个具有许多不同属性和许多不同节点类型的复杂图,你想把一个模式和一个有很多属性的“人”匹配起来

在没有索引的情况下,您别无选择,只能遍历该图,在该图中,可能只有0.01%的节点属于person类型。遍历可能不会到达图的未连接区域

相反,如果我为每个人编制了索引,我只需遍历每个人,并在每个人周围进行局部搜索,查看他们的模式是否匹配

您应该能够立即看到,第一种方法随图形的总大小进行缩放,而第二种方法仅随图形中的总人数进行缩放

寓意:如果您设想一个用例,其中将有许多对图形的搜索,其中特定类型的节点作为模式中的绑定节点(例如,这里有很多对“具有模式X的人”的搜索),那么您应该为这些节点编制索引,以提高搜索性能


如果您要搜索“person-Peter两个链接中的所有节点”,那么根据其名称索引person将是至关重要的,并且无论图形大小如何,都将允许恒定的时间性能,因为您基本上是在哈希表中查找Peter的位置。

因此,总之,使用索引属性允许工作