-file-name.csv在上一个问题上 How to make the Cypher request to handle those both cases without duplicating Nodes
我做的第一步
CREATE CONSTRAINT ON (r:Region) ASSERT r.region IS UNIQUE;
CREATE CONSTRAINT ON (c:City) ASSERT c.cityName IS UNIQUE;
CREATE CONSTRAINT ON (s:Sector) ASSERT s.sectorName IS UNIQUE;
这里我把cypher查询。
LOAD CSV WITH HEADERS FROM "file:///the-file-name.csv" as line
FIELDTERMINATOR ','
with line as line
OPTIONAL MATCH (n:Region)
WHERE n.region contains "BLANKEMPTYVIDE" AND n.identifier= line.CODE_TER
WITH n, line
CALL apoc.do.when(
n IS NULL,
'MERGE (r:Region{region: line.TERRITOIRE}) ON CREATE SET r.description=line.TERRITOIRE ON CREATE SET r.identifier=line.CODE_TER ON CREATE SET r.id = toString(id(r)) RETURN r',
'RETURN n AS r',
{n: n, line: line}) YIELD value
WITH value.r AS r, line
SET r.identifier=line.CODE_TER
SET r.description=line.TERRITOIRE
SET r.region=line.TERRITOIRE
WITH r,line
OPTIONAL MATCH (ci:City) where ci.cityName contains "BLANKEMPTYVIDE" AND ci.regionIdentifier= line.CODE_TER
CALL apoc.do.when(
ci IS NULL,
'MERGE (c:City {cityName:line.BRICK}) ON CREATE SET c.identifier=line.CODE_BRICK ON CREATE SET c.region=line.TERRITOIRE ON CREATE SET c.regionIdentifier=line.CODE_TER ON CREATE SET c.zip=line.CODE_BRICK ON CREATE SET c.description=line.BRICK ON CREATE SET c.id = toString(id(c)) RETURN c',
'RETURN ci AS c',
{ci: ci, line: line}) YIELD value
WITH value.c AS c,line,r
SET c.identifier=line.CODE_BRICK
SET c.region=line.TERRITOIRE
SET c.regionIdentifier=line.CODE_TER
SET c.zip=line.CODE_BRICK
SET c.description=line.BRICK
SET c.cityName=line.BRICK
WITH c,r,line
MATCH (c {identifier:line.CODE_BRICK}),(r {identifier:line.CODE_TER})
MERGE (c)-[:IS_A_City_BELONGING_TO]->(r)
WITH c,r,line
OPTIONAL MATCH (sec:Sector)
WHERE sec.description contains "BLANKEMPTYVIDE" AND sec.regionIdentifier=line.CODE_TER
CALL apoc.do.when(
sec IS NULL,
'MERGE (s:Sector {sectorName:line.SOUSBRICK}) ON CREATE SET s.identifier=line.CODE_SBRICK ON CREATE SET s.region=line.TERRITOIRE ON CREATE SET s.regionIdentifier=line.CODE_TER ON CREATE SET s.city=line.BRICK ON CREATE SET s.cityIdentifier=line.CODE_BRICK ON CREATE SET s.description=line.SOUSBRICK ON CREATE SET s.zip=line.SOUSBRICK ON CREATE SET s.id = toString(id(s)) RETURN s',
'RETURN sec AS s',
{sec: sec, line: line}) YIELD value
WITH value.s AS s,line,c,r
SET s.identifier=line.CODE_SBRICK
SET s.region=line.TERRITOIRE
SET s.regionIdentifier=line.CODE_TER
SET s.city=line.BRICK
SET s.cityIdentifier=line.CODE_BRICK
SET s.description=line.SOUSBRICK
SET s.zip=line.SOUSBRICK
SET s.sectorName = line.SOUSBRICK
WITH s,c,r,line
MATCH (s {identifier:line.CODE_SBRICK}),(r{identifier:line.CODE_TER})
MERGE (s)-[:IS_A_SECTOR_BELONGING_TO_THAT_REGION]->(r)
WITH s,c,r,line
MATCH (s {identifier:line.CODE_SBRICK}),(c{identifier:line.CODE_BRICK})
MERGE (s)-[:IS_A_SECTOR_BELONGING_TO_THAT_CITY]->(c)
结果:
设置28271个属性,创建3400个关系,在34985毫秒后完成。
将csv加载到neo4j db需要35秒。 请问在性能方面是否完美?
表示包含1665个csv行的csv文件 每行包含6个字段:(Region)第三个和第四个(City)的两个第一个字段,(Sector)的第五个和第六个字段。
如何优化这个neo4j查询,以便在3秒内只需几秒钟?
下面我将调查结果图片放入。
在这里,我根据InverseFalcon的建议进行了更新
LOAD CSV WITH HEADERS FROM "file:///the-file-name.csv" as line
FIELDTERMINATOR ','
with line as line
OPTIONAL MATCH (n:Region)
WHERE n.region contains "BLANKEMPTYVIDE" AND n.identifier= line.CODE_TER
WITH n, line
CALL apoc.do.when(
n IS NULL,
'MERGE (r:Region{region: line.TERRITOIRE}) ON CREATE SET r.description=line.TERRITOIRE ON CREATE SET r.identifier=line.CODE_TER ON CREATE SET r.id = toString(id(r)) RETURN r',
'SET n.identifier=line.CODE_TER SET n.description=line.TERRITOIRE SET n.region=line.TERRITOIRE RETURN n AS r',
{n: n, line: line}) YIELD value
WITH value.r AS r, line
OPTIONAL MATCH (ci:City) where ci.cityName contains "BLANKEMPTYVIDE" AND ci.regionIdentifier= line.CODE_TER
CALL apoc.do.when(
ci IS NULL,
'MERGE (c:City {cityName:line.BRICK}) ON CREATE SET c.identifier=line.CODE_BRICK ON CREATE SET c.region=line.TERRITOIRE ON CREATE SET c.regionIdentifier=line.CODE_TER ON CREATE SET c.zip=line.CODE_BRICK ON CREATE SET c.description=line.BRICK ON CREATE SET c.id = toString(id(c)) RETURN c',
'SET ci.identifier=line.CODE_BRICK SET ci.region=line.TERRITOIRE SET ci.regionIdentifier=line.CODE_TER SET ci.zip=line.CODE_BRICK SET ci.description=line.BRICK SET ci.cityName=line.BRICK RETURN ci AS c',
{ci: ci, line: line}) YIELD value
WITH value.c AS c,line,r
MERGE (c)-[:IS_A_City_BELONGING_TO]->(r)
WITH c,r,line
OPTIONAL MATCH (sec:Sector)
WHERE sec.description contains "BLANKEMPTYVIDE" AND sec.regionIdentifier=line.CODE_TER
CALL apoc.do.when(
sec IS NULL,
'MERGE (s:Sector {sectorName:line.SOUSBRICK}) ON CREATE SET s.identifier=line.CODE_SBRICK ON CREATE SET s.region=line.TERRITOIRE ON CREATE SET s.regionIdentifier=line.CODE_TER ON CREATE SET s.city=line.BRICK ON CREATE SET s.cityIdentifier=line.CODE_BRICK ON CREATE SET s.description=line.SOUSBRICK ON CREATE SET s.zip=line.SOUSBRICK ON CREATE SET s.id = toString(id(s)) RETURN s',
'SET sec.identifier=line.CODE_SBRICK SET sec.region=line.TERRITOIRE SET sec.regionIdentifier=line.CODE_TER SET sec.city=line.BRICK SET sec.cityIdentifier=line.CODE_BRICK SET sec.description=line.SOUSBRICK SET sec.zip=line.SOUSBRICK SET sec.sectorName = line.SOUSBRICK RETURN sec AS s',
{sec: sec, line: line}) YIELD value
WITH value.s AS s,line,c,r
MERGE (s)-[:IS_A_SECTOR_BELONGING_TO_THAT_REGION]->(r)
WITH s,c,r,line
MERGE (s)-[:IS_A_SECTOR_BELONGING_TO_THAT_CITY]->(c)
为部门描述添加了索引 约束成为
CREATE CONSTRAINT ON (r:Region) ASSERT r.region IS UNIQUE;
CREATE CONSTRAINT ON (c:City) ASSERT c.cityName IS UNIQUE;
CREATE CONSTRAINT ON (s:Sector) ASSERT s.sectorName IS UNIQUE;
CREATE CONSTRAINT ON (s:Sector) ASSERT s.description IS UNIQUE;
从分析器计划
Cypher版本:CYPHER 3.4,规划器:COST,运行时间:解释。在14321毫秒内总共有175350次点击率****
直接没有Profiler 创建3403关系,在12702毫秒后完成。
从36秒到12秒的良好增强,但仍需要优化。
答案 0 :(得分:0)
具有最大数据库命中的操作引用NodeByLabelScan,后跟过滤器,仅产生1663行或来自标签的起始130万个节点的结果。如果可能的话,这似乎是一个添加索引的机会。
您还没有在查询计划中扩展节点,因此我们无法看到与这些数据库命中相关联的查询部分的任何信息,但是如果我猜测它将来自此处:
OPTIONAL MATCH (sec:Sector)
WHERE sec.description contains "BLANKEMPTYVIDE" AND sec.regionIdentifier=line.CODE_TER
我没有看到任何证据表明您已经创建了约束或索引:扇区(描述)或:扇区(regionIdentifier),因此这可能是规划者被迫使用NodeByLabelScan的地方,正如您所看到的太贵了。您将需要其中一个索引或一个唯一约束(取决于这些属性中的任何一个是否是唯一的:Sector)。
另外,你在整个查询中的几个地方做了一件奇怪的事情,如下所示:
MATCH (s {identifier:line.CODE_SBRICK}),(r{identifier:line.CODE_TER})
你在MATCH中使用的变量已经绑定了,所以我建议使用WHERE子句来表明这是一个过滤步骤:
WITH s,c,r,line
WHERE s.identifier = line.CODE_SBRICK AND r.identifier = line.CODE_TER
也就是说,在所有这些情况下,您已经明确地将这些属性设置为相关的行属性,因此无需执行此类过滤,这是不必要的。我建议删除那些匹配,然后合并关系。