我在 Neo4j 中运行相同的查询,并注意到执行时间差异很大。例如,查询可能会在 5-6 秒内执行,而在其他时间则需要 2-3 分钟,即使数据保持不变。
:param {
idsToExclude: []
};
:auto LOAD CSV WITH HEADERS FROM ('file:///PERSON_DATA.csv') AS row
WITH row
WHERE NOT row.`person_id` IN $idsToExclude AND NOT row.`person_id` IS NULL
CALL {
WITH row
MERGE (n: `Person` { `person_id`: row.`person_id` })
SET n.`person_id` = row.`person_id`
SET n.`name` = row.`name`
SET n.`age` = toInteger(row.`age`)
SET n.`email` = row.`email`
SET n.`address` = row.`address`
SET n.`creation_date` = datetime(row.`creation_date`)
SET n.`last_modified_date` = datetime(row.`last_modified_date`)
} IN TRANSACTIONS OF 5000 ROWS;
这是我的配置文件中的一些数据,如果需要,已取消注释
server.memory.heap.initial_size=8G
server.memory.heap.max_size=16G
dbms.memory.transaction.total.max=32G
解释我的查询
为什么在 Neo4j 中执行相同的查询会花费不同的时间?哪些因素会影响这一点,以及如何优化其性能?
速度减慢的原因是您在
:Person(person_id)
上没有索引,这可以解释为什么早期运行(数据很少)执行速度很快,但随着数据加载或通过更大的 CSV 进行摄取而变得越来越昂贵。
如果没有索引,MERGE 的 MATCH 部分的成本(因为 MERGE 类似于 MATCH,然后是 CREATE,如果没有找到匹配项)会随着图中 :Person 节点的数量线性增加。使用索引,成本仍然会上升,但由于索引的使用,其复杂性为 log(n),因此应该保持高效。
添加索引,确认 EXPLAIN 计划中使用了该索引(您应该看到 NodeIndexSeek 运算符,并且没有 NodeByLabelScan 运算符),然后再次测试。