我使用的Neo4j来表示我们的数据仓库。我们有大约100,000个各种类型的节点(约10个),其中一些节点有多个标签。典型的节点类型的一个子集是:最佳Neo4j的指数策略多重标记节点
(:User)
(:Tableau:Workbook)
(:Tableau:Dashboard)
这里Tableau
表示数据可视化软件和Workbook
和Dashboard
是不同的Tableau实体。我们与多个标签去,而不是一个单一的唯一定义标签的原因是一个可能要匹配所有(:Tableau)
节点或全部(:Dashboard)
节点(我们有多个仪表盘源)。
我还使用GraphAware Neo4j UUID库(https://github.com/graphaware/neo4j-uuid)确保每个节点(不论类型)通过uuid
节点属性唯一标识。
我们为您的每一个节点的标签,以提高性能的指标(和唯一性约束),即
CREATE INDEX ON:User(uuid)
CREATE INDEX ON:Tableau(uuid)
CREATE INDEX ON:Workbook(uuid)
CREATE INDEX ON:Dashboard(uuid)
因为CREATE INDEX
必须正好有一个标签。
我碰到使用暗号给这个索引结构匹配的节点时,一些性能问题。即使的(:Tableau:Dashboard)
< < (:Tableau)
以下查询基数是次优
MATCH (n:Tableau:Dashboard) WHERE n.uuid = <UUID>
相比,无论
MATCH (n:Tableau) WHERE n.uuid = <UUID>
MATCH (n:Dashboard) WHERE n.uuid = <UUID>
因为前者没有利用虽然后来做任何指数
。
:如果一个人想找到全球仅基于UUID(这是唯一的)一个节点,其往往是在我们使用的烧瓶API来查找节点翻译为下面的Cypher逻辑的情况下,这个问题更加复杂MATCH(n) WHERE n.uuid = <UUID>
以下螺纹建议创建Entity
全球总体节点标签并创建在该索引(Neo4j: Create index for nodes with same property)
CREATE INDEX ON:Entity(uuid)
所以现在与如下进行标记节点,
(:Entity:User)
(:Entity:Tableau:Workbook)
(:Entity:Tableau:Dashboard)
这是最好的方法?如果定义了多个标签,并且保证了索引,那么另一种解决方案就是只选择第一个标签,但它不能解决单纯根据UUID查找节点的问题。
如果我使用Entity
标签方法,保留所有先前定义的索引仍然有意义,即,如果我只搜索节点的一小部分,我是否期望看到显着的性能改进?例如,如果我知道n
是(:User)
节点我应该会看到类似的表演,
MATCH (n:Entity) WHERE n.uuid = <UUID>
MATCH (n:User) WHERE n.uuid = <UUID>
不具有能力上没有或多个索引的索引是因为最佳的Cypher查询可能是比较抽象的一个耻辱即,比方说,一个(:Tableau:Workbook)
填充一个(:Tableau:Dashboard)
然后找到工作簿填充一个将查询仪表盘,
MATCH (s:Tabeau:Workbook)-[:POPULATES]->(t:Tableau:Dashboard)
WHERE s.uuid = <UUID>
RETURN t
这是相当透明的,而下面是从性能的角度更优化的,尽管不那么透明鉴于这不是显而易见的是什么类型的节点s
的是用户,
MATCH (s:Entity)-[:POPULATES]->(t:Tableau:Dashboard)
WHERE s.uuid = <UUID>
RETURN t
谢谢。我不知道可以强制使用索引。我意识到我有重叠的索引,但是这是一件坏事?这样,我可以在匹配任何节点类型时始终使用索引,即“MATCH(n:Dashboard)USING INDEX n:Dashboard(uuid)”,除非我不确定类型。 – John
np。当然,由于数据库的小尺寸保持重叠索引不会成为问题。如果你有一个商业案例,它超过了维护一个特定属性上的索引的额外开销两次,那么我说去吧。 –