【问题标题】:How to tell cypher where to make nodehashjoin如何告诉密码在哪里制作 nodehashjoin
【发布时间】:2024-01-21 19:06:02
【问题描述】:

我对某些类型的查询有非常有趣的观察。

我的起始查询是:

PROFILE 
MATCH (cs:Movie { id: 'm:H01016' }) WITH cs 
MATCH (ms:Actor { id: 'a:111' }) WITH cs,ms  
MATCH p=((cs)--(x0)--(x1)--(x2)--(ms))   
RETURN EXTRACT(n IN nodes(p) | n)  SKIP 0 LIMIT 24

使用我的数据执行 141 毫秒

对这个查询稍作修改

PROFILE 
MATCH (cs:Movie { id: 'm:H01016' }) WITH cs 
MATCH (ms:Actor { id: 'a:111' }) WITH cs,ms  
MATCH p=((cs)--(x0:Director)--(x1)--(x2)--(ms))   
RETURN EXTRACT(n IN nodes(p) | n)  SKIP 0 LIMIT 24

它开始执行 7-8 秒。我看到的唯一区别是 nodehashjoin 发生的位置。

第一个执行计划是:

第二个看起来像:

区别非常明显。在第一个查询中,我们在任一侧都有 2 个扩展,并且 nodehashjoin 发生在中间,而在第二个查询中,我们有 3 个从一侧扩展,1 个在另一侧扩展,并且 nodehashjoin 发生在最后。这 3 个对第二个查询的扩展导致超过一百万个 db 命中。那么有什么方法可以指示 nodehashjoin 必须在哪里发生?

这里是慢速执行查询的扩展版本。我相信这没有什么奇怪的。只是 nodehashjoin 发生在不合适的地方:

【问题讨论】:

  • 您的查询中到底写了什么 (x0:**Director**) ?我问是因为这似乎不是有效的语法...
  • x0:导演。 ** 打开像 xxx 这样的粗体部分。我不知道为什么它不起作用,我也没有注意到它,并且评论中的 ofc 正在起作用。也许它在代码部分不起作用。
  • 酷,谢谢。您能否在第二个视觉对象中扩展两个过滤器和 Expand(All) 出现“错误”(突然有一百万分贝命中)的地方,并将其添加到问题中?快速的回答是你不能强制 nodehashjoin 发生在哪里,但是看看(并尝试解释)为什么会很有趣......

标签: neo4j cypher


【解决方案1】:

所以,如果你想以某种方式改变查询优化的行为,其实有一个技巧,可以使用。我没有你的数据集来测试它,但是这个子句会影响你的执行计划。这样,您可以将 Expand(all) 和过滤器更改为 Expand(Into) 运算符:

with * where true

【讨论】:

  • 究竟应该在哪里包含它,因为到目前为止我没有看到任何区别?
  • 在你的 WITH 之后的某个地方。首先我会尝试这样并在之后检查分析: PROFILE MATCH (cs:Movie { id: 'm:H01016' }) WITH cs WITH * WHERE true MATCH (ms:Actor { id: 'a:111' }) WITH cs,ms MATCH p=((cs)--(x0)--(x1)--(x2)--(ms)) RETURN EXTRACT(n IN nodes(p) | n) SKIP 0 LIMIT 24
  • 确实查询现在运行得更快了。
  • 无法理解这是如何工作的,我也找不到资源。如果在路线的一端有一组这样的 PROFILE MATCH (cs:Movie { id: 'm:H01016' }) WITH c WITH * WHERE true MATCH (ms:Actor) WHERE ms.id,它会起作用吗在 [ 'a:111', 'a:112'] WITH cs,ms MATCH p=((cs)--(x0)--(x1)--(x2)--(ms)) RETURN EXTRACT(n IN 节点 (p) | n) SKIP 0 LIMIT 24.
  • 它应该可以工作。将(无意义的)密码段放入查询中是一种技巧,密码优化器认为它应该为此 with 子句优化查询。没有其他的。类似的故事在这里:*.com/questions/40725765/…
最近更新 更多