Cypher 查询优化 - 利用节点的已知属性
Cypher query optimisation - Utilising known properties of nodes
设置:
Neo4j 和 Cypher 版本 2.2.0。
我正在查询 Neo4j 作为 Eclipse 中创建的 TestGraphDatabaseFactory().newImpermanentDatabase(); 的内存实例。
我正在使用这种方法,因为它看起来比嵌入式版本更快,而且我认为它具有相同的功能。
我的图形数据库是通过编程方式随机生成的,具有不同数量的节点。
背景:
我自动生成密码查询。这些查询用于尝试识别单个 'target' 节点。我可以使用已知的 'node' 属性来限制查询的可能匹配项。在这种情况下,我只使用 'name' 属性。如果节点有已知名称,我可以使用它来查找节点 ID 并在开始子句中使用它。除了已知名称外,我还知道(对于某些节点)是否存在已知不属于某个节点的名称。我在 where 子句中指定了它。
我的查询类型 运行 看起来像这样...
START
nvari = node(5)
MATCH
(target:C5)-[:IN_LOCATION]->(nvara:LOCATION),
(nvara:LOCATION)-[:CONNECTED]->(nvarb:LOCATION),
(nvara:LOCATION)-[:CONNECTED]->(nvarc:LOCATION),
(nvard:LOCATION)-[:CONNECTED]->(nvarc:LOCATION),
(nvard:LOCATION)-[:CONNECTED]->(nvare:LOCATION),
(nvare:LOCATION)-[:CONNECTED]->(nvarf:LOCATION),
(nvarg:LOCATION)-[:CONNECTED]->(nvarf:LOCATION),
(nvarg:LOCATION)-[:CONNECTED]->(nvarh:LOCATION),
(nvari:C4)-[:IN_LOCATION]->(nvarg:LOCATION),
(nvarj:C2)-[:IN_LOCATION]->(nvarg:LOCATION),
(nvare:LOCATION)-[:CONNECTED]->(nvark:LOCATION),
(nvarm:C3)-[:IN_LOCATION]->(nvarg:LOCATION),
WHERE
NOT(nvarj.Name IN ['nf']) AND NOT(nvarm.Name IN ['nb','nj'])
RETURN DISTINCT target
考虑这个问题的另一种方式(如果有帮助的话)是,这是一个同构测试问题,我们有一些关于查询和目标图中的节点如何基于标签限制相互对应的信息。
问题:
关于优化:
- 在匹配子句中包含关系变量是否有帮助?我把它们去掉是因为节点变量足以区分关系,但这可能会减慢速度?
我是否应该重组 match 子句以让 match/where 对包括我之前示例中的 where 子句?我的期望是他们可以尽早限制可能的绑定。例如...
开始
nvari = 节点 (5)
匹配
(nvarj:C2)-[:IN_LOCATION]->(nvarg:LOCATION)
哪里没有(nvarj.Name 在 ['nf'] 中)
匹配
(nvarm:C3)-[:IN_LOCATION]->(nvarg:LOCATION)
哪里没有(nvarm.Name 在 ['nb','nj'])
匹配
(target:C5)-[:IN_LOCATION]->(nvara:LOCATION),
(nvara:LOCATION)-[:CONNECTED]->(nvarb:LOCATION),
(nvara:LOCATION)-[:CONNECTED]->(nvarc:LOCATION),
(nvard:LOCATION)-[:CONNECTED]->(nvarc:LOCATION),
(nvard:LOCATION)-[:CONNECTED]->(nvare:LOCATION),
(nvare:LOCATION)-[:CONNECTED]->(nvarf:LOCATION),
(nvarg:LOCATION)-[:CONNECTED]->(nvarf:LOCATION),
(nvarg:LOCATION)-[:CONNECTED]->(nvarh:LOCATION),
(nvare:LOCATION)-[:CONNECTED]->(nvark:LOCATION)
RETURN 不同的目标
侧面:
- (不太重要但仍然很有趣)如果我将匹配子句中的每个关系都设为可选匹配,但包含目标节点的关系除外,那么 cypher 本质上是在查询和图之间找到最大公共子图具有 MCS 包含目标节点的约束的数据库?
提前致谢!我希望我已经明确了我的要求,但我明白这不是 Neo4j 的典型用例。
我认为使用节点属性进行查询几乎总是比使用关系属性更可取(如果您有选择的话),因为这开启了索引有助于加快查询速度的可能性。
顺便说一句,如果可能值的集合只有一个元素,我会避免使用 IN
运算符。例如,这个片段:NOT(nvarj.Name IN ['nf'])
,应该是 (nvarj.Name <> 'nf')
。当前版本的 Cypher 可能不会为 IN
运算符使用索引。
重构查询以更早地消除不需要的绑定正是您应该做的。
首先,您需要至少对查询中的第一个关系(绑定 target
)继续使用 MATCH
,否则您的结果将包含很多 null
行 -- 不是很有用。
但是,仔细想想,如果所有其他关系都放在单独的 OPTIONAl MATCH
子句中,那么即使 none 个可选匹配成功。因此,逻辑等价物是:
MATCH (target:C5)-[:IN_LOCATION]->(nvara:LOCATION)
RETURN DISTINCT target
我认为这不是有用的结果。
设置:
Neo4j 和 Cypher 版本 2.2.0。 我正在查询 Neo4j 作为 Eclipse 中创建的 TestGraphDatabaseFactory().newImpermanentDatabase(); 的内存实例。 我正在使用这种方法,因为它看起来比嵌入式版本更快,而且我认为它具有相同的功能。 我的图形数据库是通过编程方式随机生成的,具有不同数量的节点。
背景:
我自动生成密码查询。这些查询用于尝试识别单个 'target' 节点。我可以使用已知的 'node' 属性来限制查询的可能匹配项。在这种情况下,我只使用 'name' 属性。如果节点有已知名称,我可以使用它来查找节点 ID 并在开始子句中使用它。除了已知名称外,我还知道(对于某些节点)是否存在已知不属于某个节点的名称。我在 where 子句中指定了它。
我的查询类型 运行 看起来像这样...
START
nvari = node(5)
MATCH
(target:C5)-[:IN_LOCATION]->(nvara:LOCATION),
(nvara:LOCATION)-[:CONNECTED]->(nvarb:LOCATION),
(nvara:LOCATION)-[:CONNECTED]->(nvarc:LOCATION),
(nvard:LOCATION)-[:CONNECTED]->(nvarc:LOCATION),
(nvard:LOCATION)-[:CONNECTED]->(nvare:LOCATION),
(nvare:LOCATION)-[:CONNECTED]->(nvarf:LOCATION),
(nvarg:LOCATION)-[:CONNECTED]->(nvarf:LOCATION),
(nvarg:LOCATION)-[:CONNECTED]->(nvarh:LOCATION),
(nvari:C4)-[:IN_LOCATION]->(nvarg:LOCATION),
(nvarj:C2)-[:IN_LOCATION]->(nvarg:LOCATION),
(nvare:LOCATION)-[:CONNECTED]->(nvark:LOCATION),
(nvarm:C3)-[:IN_LOCATION]->(nvarg:LOCATION),
WHERE
NOT(nvarj.Name IN ['nf']) AND NOT(nvarm.Name IN ['nb','nj'])
RETURN DISTINCT target
考虑这个问题的另一种方式(如果有帮助的话)是,这是一个同构测试问题,我们有一些关于查询和目标图中的节点如何基于标签限制相互对应的信息。
问题:
关于优化:
- 在匹配子句中包含关系变量是否有帮助?我把它们去掉是因为节点变量足以区分关系,但这可能会减慢速度?
我是否应该重组 match 子句以让 match/where 对包括我之前示例中的 where 子句?我的期望是他们可以尽早限制可能的绑定。例如...
开始
nvari = 节点 (5)
匹配
(nvarj:C2)-[:IN_LOCATION]->(nvarg:LOCATION)
哪里没有(nvarj.Name 在 ['nf'] 中)
匹配
(nvarm:C3)-[:IN_LOCATION]->(nvarg:LOCATION)
哪里没有(nvarm.Name 在 ['nb','nj'])
匹配
(target:C5)-[:IN_LOCATION]->(nvara:LOCATION), (nvara:LOCATION)-[:CONNECTED]->(nvarb:LOCATION), (nvara:LOCATION)-[:CONNECTED]->(nvarc:LOCATION), (nvard:LOCATION)-[:CONNECTED]->(nvarc:LOCATION), (nvard:LOCATION)-[:CONNECTED]->(nvare:LOCATION), (nvare:LOCATION)-[:CONNECTED]->(nvarf:LOCATION), (nvarg:LOCATION)-[:CONNECTED]->(nvarf:LOCATION), (nvarg:LOCATION)-[:CONNECTED]->(nvarh:LOCATION), (nvare:LOCATION)-[:CONNECTED]->(nvark:LOCATION)
RETURN 不同的目标
侧面:
- (不太重要但仍然很有趣)如果我将匹配子句中的每个关系都设为可选匹配,但包含目标节点的关系除外,那么 cypher 本质上是在查询和图之间找到最大公共子图具有 MCS 包含目标节点的约束的数据库?
提前致谢!我希望我已经明确了我的要求,但我明白这不是 Neo4j 的典型用例。
我认为使用节点属性进行查询几乎总是比使用关系属性更可取(如果您有选择的话),因为这开启了索引有助于加快查询速度的可能性。
顺便说一句,如果可能值的集合只有一个元素,我会避免使用
IN
运算符。例如,这个片段:NOT(nvarj.Name IN ['nf'])
,应该是(nvarj.Name <> 'nf')
。当前版本的 Cypher 可能不会为IN
运算符使用索引。重构查询以更早地消除不需要的绑定正是您应该做的。
首先,您需要至少对查询中的第一个关系(绑定
target
)继续使用MATCH
,否则您的结果将包含很多null
行 -- 不是很有用。但是,仔细想想,如果所有其他关系都放在单独的
OPTIONAl MATCH
子句中,那么即使 none 个可选匹配成功。因此,逻辑等价物是:MATCH (target:C5)-[:IN_LOCATION]->(nvara:LOCATION) RETURN DISTINCT target
我认为这不是有用的结果。