py2neo cursor全量加载数据到内存而非流式传输问题求解
问题根因
py2neo默认执行g.run(query)时会一次性拉取全量结果集到本地内存,完成拉取后才会返回可迭代的cursor对象。1亿行的场景下,程序会卡在数据拉取阶段占满内存,根本走不到后续的迭代写文件逻辑,因此你看不到打印输出,也没有数据写入磁盘。
解决办法
- 方案1:调整py2neo查询的拉取批次,改动最小
给run方法添加fetch_size参数,指定每批次拉取的行数,即可实现边拉取边迭代,不会一次性加载全量数据。同时补充操作系统级的缓存刷入逻辑,保证落盘生效。
修改后代码示例:
from py2neo import Graph import csv import os # 每批次拉取5万行,和你当前的计数阈值对齐 cursor = g.run(query, fetch_size=50000) with open('bigfile.csv', 'w', newline='', encoding='utf-8') as csvfile: fieldnames = cursor.keys() writer = csv.writer(csvfile) # 如果需要写表头取消下面注释 # writer.writerow(fieldnames) i = 0 j = 1 for rec in cursor: writer.writerow(rec.values()) i +=1 if i == 50000: print(str(i*j) + '...') csvfile.flush() # 强制刷入操作系统缓存到磁盘 os.fsync(csvfile.fileno()) i = 0 j +=1
- 方案2:替换为Neo4j官方Python驱动,稳定性更高
如果py2neo的批次参数设置不生效,直接使用官方neo4j驱动,原生支持流式分批拉取,内存占用可以稳定在百兆级别。代码示例如下:
from neo4j import GraphDatabase import csv import os uri = "你的Neo4j服务地址" auth = ("你的用户名", "你的密码") batch_size = 50000 with GraphDatabase.driver(uri, auth=auth) as driver, \ driver.session() as session, \ open('bigfile.csv', 'w', newline='', encoding='utf-8') as csvfile: result = session.run(query) fieldnames = result.keys() writer = csv.writer(csvfile) # 如果需要写表头取消下面注释 # writer.writerow(fieldnames) i = 0 j = 1 for rec in result: writer.writerow(rec.values()) i += 1 if i == batch_size: print(f"{i*j}...") csvfile.flush() os.fsync(csvfile.fileno()) i = 0 j += 1
- 额外优化建议
- 如果1亿行单文件过大,可以每写1000万行切换新的csv文件,避免单文件过大后续读写、传输困难
- 可以给查询涉及的字段添加适当的索引,加快Neo4j端的查询返回速度,减少整体耗时
内容的提问来源于stack exchange,提问作者posdef
相关产品推荐
相关产品推荐

