我使用 Neo4j 来代表我们的数据仓库。我们有约 100,000 个各种类型的节点(约 10 个),其中一些具有多个标签。典型节点类型的子集是:
(: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
必须恰好采用一个标签。
在给定此索引结构的情况下使用 Cypher 匹配节点时,我遇到了一些性能问题。即使
(: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(唯一)全局查找节点,这个问题就会变得更加复杂,当我们使用 Flask API 查找节点时经常出现这种情况,这会转化为以下 Cypher 逻辑:
MATCH(n) WHERE n.uuid = <UUID>
以下线程建议创建一个
Entity
总体全局节点标签并在其上创建索引(Neo4j:为具有相同属性的节点创建索引),
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
您正在维护
Tableau
和 Workbook
以及 Tableau
和 Dashboard
的重叠索引。为什么不只维护 Tableau
的索引来消除冗余,并用 USING INDEX
向查询规划器发出提示,以确保它在您的匹配中使用。即类似这样的东西...
MATCH (s:Tableau:Workbook)-[:POPULATES]->(t:Tableau:Dashboard)
USING INDEX s:Tableau(uuid)
WHERE s.uuid = <UUID>
RETURN t
对于那些找到此线程的人,即使有 2 个以上标签,Neo4j 的最新版本(我使用的是 v5)也会使用索引。
MATCH (s:Tableau:Workbook) WHERE s.uuid = <uuid>
假设您在
Tableau
上有索引,但在 Workbook
上没有 ,这与 OP 中的情况略有不同。
Tableau
索引
:Workbook
。
s:Tableau
慢了一根头发,但可能可以忽略不计。文档
搜索性能指数:
“如果有多个索引可用,Cypher planner 将尝试使用能够最有效地解决特定谓词的索引(或多个索引)”索引提示
文档阐明您仍然可以添加USING INDEX
提示(根据
@dave-bennett的好建议,但这仅在更高级的情况下才有必要。