【问题标题】:Neo4j not using indicesNeo4j 不使用索引
【发布时间】:2015-06-05 13:33:08
【问题描述】:

目前我正在 Neo4j 2.2.2 上尝试此查询

在撰写本文时,我们尚未标记任何节点,因为我们最近从 Neo4j 1.x 升级。所以我们没有使用 USING 子句的选项。

我正在尝试使用索引,但以全表扫描结束。

START pfComp=node:Company('id:2403226') , ptComp=node:Company('id:1946633')
OPTIONAL MATCH
     (pfComp)<-[c:CHILD_OF*]-(cfComp)
WITH collect(id(cfComp)) as cfCompIds, ptComp, pfComp
OPTIONAL MATCH
                (ptComp)<-[c2:CHILD_OF*]-(ctComp)
WITH  cfCompIds, collect(id(ctComp)) AS ctCompIds
MATCH
                (fComp) -[fR:PARTICIPATES_IN]->  cdeals <-[tR:PARTICIPATES_IN]-(tComp)
WHERE
                (fComp.id = 2403226 or id(fComp) in  cfCompIds) and
                (tComp.id = 1946633 or id(tComp) in ctCompIds)
RETURN fComp, tComp, cdeals

Cypher 版本:CYPHER 2.2,规划器:COST。 1305292 总 db hits in 79128 ms。

对此的任何帮助将不胜感激。

以下是完整的配置文件命令输出。

查询的开头部分执行得很快:

profile START pfComp=node:Company('id:2403226') , ptComp=node:Company('id:1946633')
OPTIONAL MATCH
     (pfComp)<-[c:CHILD_OF*]-(cfComp)
WITH collect(id(cfComp)) as cfCompIds, ptComp, pfComp
OPTIONAL MATCH
                (ptComp)<-[c2:CHILD_OF*]-(ctComp)
return   cfCompIds, collect(id(ctComp)) AS ctCompIds

Cypher 版本:CYPHER 2.2,规划器:COST。在 582 毫秒内总共有 836 次 db 命中。

【问题讨论】:

  • 也许你这里有错字?你使用了你之前没有初始化过的标识符,所以它必须做一个非常糟糕的完整扫描并展开:OPTIONAL MATCH (ptComp)&lt;-[c2:CHILD_OF*]-(ctComp)
  • 这些在这里定义它们的查找的方式不一致,对于属性查找,您错过了标签,并且 id() 查找与 prop 查找冲突,我将其拆分为联合的两个部分
  • Michael Hunger:查询的请求部分很好:profile START pfComp=node:Company('id:2403226') , ptComp=node:Company('id:1946633') OPTIONAL MATCH ( pfComp)

标签: neo4j


【解决方案1】:

您的第二部分看起来像一个关系连接,或者一个额外的查找(像一个 n+1 选择)。 也许改用图形模型?查询也变得更简单了。

因此,您将使用初始匹配计算 fComptComp,因为 *0.. 它分别包含 pfComp 和 ptComp。

那么你就有了最后一场比赛的 fComp 和 tComp 之间的交叉。

请尝试一下,看看效果如何:

MATCH (pfComp:lCompany)<-[c:CHILD_OF*0..]-(fComp:lCompany)
WHERE pfComp.id = 2403226
// reduce cardinality for following match
WITH collect(distinct fComp) as companies1
MATCH (ptComp:lCompany)<-[c2:CHILD_OF*]-(tComp:lCompany)
WHERE ptComp.id = 1946633
// create cross product between fComp and tComp
UNWIND companies1 as fComp
MATCH (fComp) -[fR:PARTICIPATES_IN]->(cdeals)<-[tR:PARTICIPATES_IN]-(tComp)
RETURN  fComp, tComp, cdeals;

【讨论】:

  • 没想到会因此获得更好的性能,但您将性能提高了 3 倍。谢谢好先生。密码版本:CYPHER 2.2,计划者:COST。 307 毫秒内总共 40525 次 db 命中。
  • 好时光!使用图表 Luke :) 如果您觉得可以,请接受答案。不同的是使用图操作(扩展)而不是数千个索引查找。
【解决方案2】:

您的个人资料中有 个索引查询 (NodeByQueryIndex)。

您可以定义要在查询中使用的索引:

MATCH (n:Swedish)
USING INDEX n:Swedish(surname)
WHERE n.surname = 'Taylor'
RETURN n

http://neo4j.com/docs/stable/query-using.html

【讨论】:

  • 我们使用的是遗留索引。 dba 刚刚放入标签,我将使用新标签节点的 USING 子句重试。
【解决方案3】:

我们的解决方案是创建标签 (lCompany) 并在 Company.id 列上添加更新的索引类型 (CREATE INDEX ON :lCompany(id))。

然后调整查询以使用新索引:

OPTIONAL MATCH
     (pfComp:lCompany)<-[c:CHILD_OF*]-(cfComp:lCompany)
WHERE pfComp.id = 2403226
WITH 
    collect(cfComp.id) as cfCompIds
    , pfComp
OPTIONAL MATCH
        (ptComp:lCompany)<-[c2:CHILD_OF*]-(ctComp:lCompany)
WHERE ptComp.id = 1946633
WITH  cfCompIds, 
      collect(ctComp.id)  AS ctCompIds, 
      pfComp, ptComp 
MATCH
      (fComp:lCompany) -[fR:PARTICIPATES_IN]->  cdeals <-[tR:PARTICIPATES_IN]-(tComp:lCompany)
USING INDEX fComp:lCompany(id) //tComp:lCompany(id)
WHERE
                (   
                    fComp.id in (cfCompIds + [2403226])
                ) 
                and
                (
                    tComp.id in (ctCompIds + [1946633])
                )
RETURN  fComp, tComp, cdeals

可能还可以进行进一步的优化,但这是我们目前为止所做的。

分析器结果现在是:

Cypher 版本:CYPHER 2.2,规划器:COST。 1498 毫秒内总共 134151 次 db 命中。

这是调整后的新配置文件:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-19
    • 2013-08-14
    • 1970-01-01
    • 1970-01-01
    • 2012-09-26
    相关资源
    最近更新 更多