我需要将类型为“Application”的节点与在安装该应用程序的系统上创建的用户相连接。
通常情况下,“应用程序”安装在群集对(2个系统)上,并且只有默认系统作为属性“n.System”。
“应用程序”具有命名架构:<prefix><number of 5 digits>
,例如yxz12345或ab23456等
在每个系统上都创建了用户帐户(每个系统有时最多100个)。其中一些具有类似“应用程序”的命名架构:<prefix><number of 5 digits>
,例如sdjhg12345或tzrw23456等有些不是。
“应用程序”作为“用户”属性,可以包含在u.Name = n.User
上运行的用户,或者它使用在其前缀right(u.Name, 5) = right(n.Name, 5)
之后具有相同5位数的所有“用户”。
用户名在所有系统中共享,因此我们只需要链接同一系统上的用户。
我正在使用以下查询来创建关系:
MATCH (n:Application {Id: 1})
WITH n
MATCH (s:System)-[:ClusteredWith]-(c:System)
WHERE s.Name = n.System
WITH n, s, c
MATCH (u:User)
WHERE
((u)-[:CreatedOn]->(s) OR (u)-[:CreatedOn]->(c))
AND
(u.Name = n.User OR right(u.Name, 5) = right(n.Name, 5))
CREATE UNIQUE (u)-[:UsedFor]->(n)
目前neo4j数据库中有8000个系统,100000个用户和30000个应用程序。
我在Id,Name,User
上有自动属性索引在非常强大的硬件(最高96 GB RAM等)上,此查询速度极慢。 我正在使用Neo4jClient版本1.0.0.646和Neo4j 2.0.1
如何快速获得此查询?
编辑:已添加查询计划:
==> EmptyResult(_rows=0, _db_hits=0)
==> UpdateGraph(commands=[{"action": "CreateUnique", "identifiers": ["u", "n", " UNNAMED305"]}], _rows=0, _db_hits=0)
==> Eager(_rows=0, _db_hits=0)
==> Filter(pred="((nonEmpty(PathExpression((u)-[ UNNAMED165:CreatedOn]->(s), true)) OR nonEmpty(PathExpression((u)-[ UNNAMED196:CreatedOn]->(c), true))) AND (Property(u,Name(0)) == Property(n,User(33)) OR RightFunction(Property(u,Name(0)),Literal(5)) == RightFunction(Property(n,Name(0)),Literal(5))))", _rows=0, _db_hits=29774466)
==> NodeByLabel(identifier="u", _db_hits=0, _rows=4962411, label="User", identifiers=["u"], producer="NodeByLabel")
==> ColumnFilter(symKeys=["n", "c", "s", " UNNAMED58"], returnItemNames=["n", "s", "c"], _rows=183, _db_hits=0)
==> Filter(pred="(Property(s,Name(0)) == Property(n,System(36)) AND hasLabel(s:System(0)))", _rows=183, _db_hits=366)
==> SimplePatternMatcher(g="(c)-[' UNNAMED58']-(s)", _rows=183, _db_hits=4880)
==> NodeByLabel(identifier="c", _db_hits=0, _rows=2915, label="System", identifiers=["c"], producer="NodeByLabel")
==> Filter(pred="Property(n,Id(0)) == Literal(1)", _rows=1, _db_hits=702)
==> NodeByLabel(identifier="n", _db_hits=0, _rows=702, label="Application", identifiers=["n"], producer="NodeByLabel")
这是对2个系统上的应用程序的查询,但没有匹配的用户(当前)
答案 0 :(得分:1)
查询您的查询(how?)并查看执行计划时请注意以下事项:
:Application(Id)
是唯一的吗?:Application(System) = :System(Name)
需要多少次数据库点击?可以通过关联(:Application)-[:InstalledOn]->(:System)
来完全避免它们吗?WITH n, s, c
绑定了重复的路径/结果项?
(s:System)-[:ClusteredWith]-(c:System)
是对称的WHERE
子句很复杂,可能太复杂而引擎无法重构到精确查找。您是否可以重构它以允许初始索引查找,甚至更好地通过(:System)<-[:CreatedOn]-(:User)
与用户联系以避免处理所有不相关的用户?我的猜测是大瓶颈是用户查找。如果查询中的该点也有多个结果项,则问题会更加复杂。以下是猜测,但也许你可以调整它并让它发挥作用。
MATCH (app:Application {Id: 1})
MATCH (:System {Name:app.System})-[:ClusteredWith*0..1]-(sys:System)<-[:CreatedOn]-(user)
WHERE (user.Name = app.User OR right(user.Name, 5) = right(app.Name, 5))
CREATE UNIQUE (user)-[:UsedFor]->(app)