索引属性上的声明需要花费太多时间

时间:2016-08-01 07:30:12

标签: neo4j cypher

我有一个密码查询如下:

MATCH (u:User {uid:"984172414"})-[ru:EB]->
(c:Co)<-[rf:EB]-(f:User)-[rc :EB]->(cc:Co)
WHERE (cc.uid in ["84161623"]) AND (rc.from IS NOT NULL AND rc.to IS NULL) AND
      ((
        ru.from IS NOT NULL AND
        ru.to IS NOT NULL AND
        (
            (rf.from <= ru.to) OR
            (ru.from <= rf.to)
        )
      ) OR (
        ru.from IS NOT NULL AND
        ru.to IS NULL AND
        (
            (ru.from <= rf.to) OR
            (rf.from IS NOT NULL AND rf.to IS NULL)
        )
      ) OR (
       ru.from IS NULL AND
       ru.to IS NOT NULL AND
        (
            (rf.from <= ru.to) OR
            (rf.from IS NULL AND rf.to IS NOT NULL)
        )
      ))
RETURN cc.name as coname,
f.name as fname,
cc.uid as cuid,
f.uid as fuid,
labels(f) as flabels,
null as version
LIMIT 20

这需要大约16192毫秒才能解决。我有一个co.uid的索引但看起来它不起作用。如果我删除了支票cc.uid in ["84161623"]并运行以下查询:

MATCH (u:User {uid:"984172414"})-[ru:EB]->
(c:Co)<-[rf:EB]-(f:User)-[rc :EB]->(cc:Co)
WHERE (rc.from IS NOT NULL AND rc.to IS NULL) AND
      ((
        ru.from IS NOT NULL AND
        ru.to IS NOT NULL AND
        (
            (rf.from <= ru.to) OR
            (ru.from <= rf.to)
        )
      ) OR (
        ru.from IS NOT NULL AND
        ru.to IS NULL AND
        (
            (ru.from <= rf.to) OR
            (rf.from IS NOT NULL AND rf.to IS NULL)
        )
      ) OR (
       ru.from IS NULL AND
       ru.to IS NOT NULL AND
        (
            (rf.from <= ru.to) OR
            (rf.from IS NULL AND rf.to IS NOT NULL)
        )
      ))
RETURN cc.name as coname,
f.name as fname,
cc.uid as cuid,
f.uid as fuid,
labels(f) as flabels,
null as version
LIMIT 20

查询仅在347毫秒内解析。我无法弄清楚(cc.uid in ["84161623"])语句有什么问题,为什么在uid上已有索引时,将此添加到查询需要16秒才能解决。任何帮助将不胜感激。

更新

根据@cybersam的建议,我尝试使用USING INDEX,但会导致以下错误:

Cannot use index hint in this context. Index hints require using an equality comparison or IN condition in WHERE (either directly or as part of a top-level AND). The comparison cannot be between two property values. Note that the label and property comparison must be specified on a non-optional node

2 个答案:

答案 0 :(得分:1)

尝试使用USING INDEX子句提供使用该索引的提示。 Cypher处理代码并不总是自动生成最有效的代码。

例如,将其放在MATCHWHERE子句之间:

USING INDEX cc:Co(uuid)

如果有其他索引,您可能还需要使用其他USING INDEX子句。但请注意,neo4j在所有情况下都不能使用索引;并且,即使可能,由于查询的其他结果更改,结果查询理论上可能会更慢。因此,请查看生成的配置文件并测试结果,以确保您对此感到满意。

答案 1 :(得分:0)

听起来你可能需要做一些健全检查。

首先,是:Co.uid是一个int还是一个字符串?看起来你正在解决它,好像它是一个字符串,但值本身看起来是数字的。如果它是一个int,你可以删除引号。

同样:User.uid。

如果您一直在将字符串与字符串进行比较,请先尝试修复它,看它是否能解决问题。如果没有,您将要开始分析并确定查询是否/何时使用您的索引。

接下来,尝试简化和分析查询以查看索引是否实际被使用:

PROFILE MATCH (u:User {uid:"984172414"}), (cc:Co)
WHERE (cc.uid in ["84161623"])
RETURN u, cc

如果他们都使用NodeIndexSeek或NodeUniqueIndexSeek,并且如果数据库命中看似合理,您可以扩展到整个路径并继续进行性能分析。但是,如果您首先匹配起始节点和结束节点,那么值得检查性能改进,如上所述,然后尝试进行额外的模式匹配。例如:

PROFILE MATCH (u:User {uid:"984172414"}), (cc:Co)
WHERE (cc.uid in ["84161623"])
WITH u, cc
MATCH (u)-[ru:EB]->(c:Co)<-[rf:EB]-(f:User)-[rc :EB]->(cc)
WHERE (rc.from IS NOT NULL AND...