您应该在此处查看索引文档:
https ://neo4j.com/docs/cypher-manual/current/administration/indexes-for-search-performance/
基本上,索引一旦创建,就允许快速查找给定标签的节点,用于给定的一个或多个属性。如果您没有索引并且您对节点进行 MATCH 或 MERGE,那么对于该 MATCH 或 MERGE 的每一行,它必须对给定标签的所有节点进行标签扫描并检查它们的所有属性以找到节点,这变得非常昂贵,尤其是在加载 CSV 时,因为这些操作可能发生在 CSV 中的每一行。
对于您的 :lapTimes 节点(尽管我们建议您在大多数情况下使用单数标签),如果您的图表中没有它们开始,那么 CREATE 而不是 MERGE 就可以了。您可能需要一个复合索引 on :lapTimes(raceId, driverId, lap)
,因为如果您以后需要查找它,它应该唯一地标识节点。在这里使用 CREATE 而不是 MERGE 应该处理得更快。
您的第二个查询应该是 MATCHing :lapTimes 节点(标签扫描),并且每个查询都在 :race 和 :driver 节点上进行索引查找,因此索引是性能的关键。
你需要索引::race(raceId)
和:Driver(driverId)
.
MATCH (lt:lapTimes)
WITH lt, lt.raceId as raceId, lt.driverId as driverId
MATCH (d:Driver), (r:race)
WHERE r.raceId = raceId AND d.driverId = driverId
MERGE (d)-[:LAPPING_AT]->(lt)
MERGE (r)-[:TIMED_LAP]->(lt)
如果您知道没有重复的条目,您可以考虑为关系创建而不是合并。
我删除了您的 RETURN 因为返回类型不是有用的信息。
此外,请考虑为您的节点标签使用一致的案例,并且您在图表中的标签和您创建的索引之间使用相同的案例。
此外,您可能希望批量处理这些更改,而不是尝试一次处理所有更改。
如果您安装 APOC 程序,您可以使用apoc.periodic.iterate()
,它可用于批量更改,这将在您的堆上更快、更容易。您仍然需要首先使用索引。
CALL apoc.periodic.iterate("
MATCH (lt:lapTimes)
WITH lt, lt.raceId as raceId, lt.driverId as driverId
MATCH (d:Driver), (r:race)
WHERE r.raceId = raceId AND d.driverId = driverId
RETURN lt, d, ir",
"MERGE (d)-[:LAPPING_AT]->(lt)
MERGE (r)-[:TIMED_LAP]->(lt)", {}) YIELD batches, total, errorMessages
RETURN batches, total, errorMessages
单个 CSV 加载
如果您想在单个 CSV 加载中一次处理所有内容,您可以这样做,但您首先需要索引。这是您至少需要的:
CREATE INDEX ON :Driver(driverId);
CREATE INDEX ON :Race(raceId);
创建这些之后,您可以使用它,假设您从头开始(我修复了标签的大小写并将它们设为单数:
USING PERIODIC COMMIT 25000
LOAD CSV WITH HEADERS from 'file:///lap_times.csv' AS row
MERGE (d:Driver {driverId:row.driverId})
MERGE (r:Race {raceId:row.raceId})
CREATE (lt:LapTime {raceId: row.raceId, driverId: row.driverId, lap: row.lap, position: row.position, time: row.time, milliseconds: row.milliseconds})
CREATE (d)-[:LAPPING_AT]->(lt)
CREATE (r)-[:TIMED_LAP]->(lt)