如何将大规模数据导入Neo4j及导入具体步骤及Demo

博文原地址:https://my.oschina.net/zlb1992/blog/918243

项目需要基于Neo4j开发,由于数据量较大(数千万节点),因此对当前数据插入的方法进行了分析和对比。

常见数据插入方式概览

Neo4j Version Language Driver
Community 3.0.2 Python neo4j-driver 1.0.0

目前主要有以下几种数据插入方式:

  1. Cypher CREATE 语句,为每一条数据写一个CREATE
  2. Cypher LOAD CSV 语句,将数据转成CSV格式,通过LOAD CSV读取数据。
  3. 官方提供的Java API —— Batch Inserter
  4. 大牛编写的 Batch Import 工具
  5. 官方提供的 neo4j-import 工具

这些工具有什么不同呢?速度如何?适用的场景分别是什么?我这里根据我个人理解,粗略地给出了一个结果:

  CREATE语句 LOAD CSV语句 Batch Inserter Batch Import Neo4j-import
适用场景 1 ~ 1w nodes 1w ~ 10 w nodes 千万以上 nodes 千万以上 nodes 千万以上 nodes
速度 很慢 (1000 nodes/s) 一般 (5000 nodes/s) 非常快 (数万 nodes/s) 非常快 (数万 nodes/s) 非常快 (数万 nodes/s)
优点 使用方便,可实时插入。 使用方便,可以加载本地/远程CSV;可实时插入。 速度相比于前两个,有数量级的提升 基于Batch Inserter,可以直接运行编译好的jar包;可以在已存在的数据库中导入数据 官方出品,比Batch Import占用更少的资源
缺点 速度慢 需要将数据转换成CSV 需要转成CSV;只能在JAVA中使用;且插入时必须停止neo4j 需要转成CSV;必须停止neo4j 需要转成CSV;必须停止neo4j只能生成新的数据库,而不能在已存在的数据库中插入数据。

速度测试

下面是我自己做的一些性能测试:

1. CREATE 语句

这里每1000条进行一次Transaction提交

 
  1. CREATE (:label {property1:value, property2:value, property3:value} )
11.5w nodes 18.5w nodes
100 s 160 s

2. LOAD CSV 语句

 
  1. using periodic commit 1000
  2. load csv from "file:///fscapture_screencapture_syscall.csv" as line
  3. create (:label {a:line[1], b:line[2], c:line[3], d:line[4], e:line[5], f:line[6], g:line[7], h:line[8], i:line[9], j:line[10]})

这里使用了语句USING PERIODIC COMMIT 1000,使得每1000行作为一次Transaction提交。

11.5w nodes 18.5w nodes
21 s 39 s

3. Batch Inserter、Batch Import、Neo4j-import

我只测试了Neo4j-import,没有测试Batch Inserter和Batch Import,但是我估计他们的内部实现差不多,速度也处于一个数量级别上,因此这里就一概而论了。

neo4j-import需要在Neo4j所在服务器执行,因此服务器的资源影响数据导入的性能,我这里为JVM分配了16G的heap资源,确保性能达到最好。

 
  1. sudo ./bin/neo4j-import --into graph.db --nodes:label path_to_csv.csv
11.5w nodes 18.5w nodes 150w nodes + 1431w edges 3113w nodes + 7793w edges
3.4 s 3.8 s 26.5 s 3 m 48 s

小结

  1. 如果项目刚开始,想要将大量数据导入数据库,Neo4j-import是最好的选择。
  2. 如果数据库已经投入使用,并且可以容忍Neo4j关闭一段时间,那么Batch Import是最好的选择,当然如果你想自己实现,那么你应该选择Batch Inserter
  3. 如果数据库已经投入使用,且不能容忍Neo4j的临时关闭,那么LOAD CSV是最好的选择。
  4. 最后,如果只是想插入少量的数据,且不怎么在乎实时性,那么请直接看Cypher语言。

Demo

1. Cypher Create语句

其主要过程就是将Cypher语句写在某个文件中,在用Java或者Python代码操作,并用jdbc连接Neo4j服务器并且执行,本方法操作太慢,仅适用于某些插入量很小的场景或者查询场景,代码不具体列出,如有需要可在下面留言。

2. Cypher LOAD CSV

在Neo4j服务器的执行命令行中直接执行如下cypher语句即可:

LOAD CSV WITH HEADERS FROM "http://data.neo4j.com/northwind/categories.csv" AS row
CREATE (n:Category)
SET n = row

categories.csv内容为

该语句是将url中,的文件以节点的形式导入neo4j中,也可用形如f:/Book1.csv的本地路径。每一行记录均生成一个节点,每个字段对应一个属性

再导入过程中还可以根据实际应用场景处理数据如:

LOAD CSV WITH HEADERS FROM "http://data.neo4j.com/northwind/products.csv" AS row
CREATE (n:Product)
SET n = row,
  n.unitPrice = toFloat(row.unitPrice),
  n.unitsInStock = toInteger(row.unitsInStock), n.unitsOnOrder = toInteger(row.unitsOnOrder),
  n.reorderLevel = toInteger(row.reorderLevel), n.discontinued = (row.discontinued <> "0")

在插入节点后可建立索引,提高后期插入关系的速度,如建立Category类型顶点上categoryID属性的索引

CREATE INDEX ON :Category(categoryID)

插入关系 如根据外键关联Prodect和Categroy的关系

MATCH (p:Product),(c:Category)
WHERE p.categoryID = c.categoryID
CREATE (p)-[:PART_OF]->(c)

系列过程可查看Neo4j中Example中的northwind-graph。该方法可以完全替代掉直接执行Cypher语句的方法,在小数据量的时候可以用。

3. Neo4j-import

在neo4j-operations-manual中有一个例子:

记录为电影,明星  以及其中存在的一个扮演角色关系。内容为
movies.csv
movieId:ID,title,year:int,:LABEL
tt0133093,"The Matrix",1999,Movie
tt0234215,"The Matrix Reloaded",2003,Movie;Sequel
tt0242653,"The Matrix Revolutions",2003,Movie;Sequel

actors.csv
personId:ID,name,:LABEL
keanu,"Keanu Reeves",Actor
laurence,"Laurence Fishburne",Actor
carrieanne,"Carrie-Anne Moss",Actor

roles.csv
:START_ID,role,:END_ID,:TYPE
keanu,"Neo",tt0133093,ACTED_IN
keanu,"Neo",tt0234215,ACTED_IN
keanu,"Neo",tt0242653,ACTED_IN
laurence,"Morpheus",tt0133093,ACTED_IN
laurence,"Morpheus",tt0234215,ACTED_IN
laurence,"Morpheus",tt0242653,ACTED_IN
carrieanne,"Trinity",tt0133093,ACTED_IN
carrieanne,"Trinity",tt0234215,ACTED_IN
carrieanne,"Trinity",tt0242653,ACTED_IN

将三个文件传至Neo4j服务器中,

执行%Neo4jHome%/bin/neo4j-import脚本,具体执行命令为:
cd至%Neo4jHome%执行

./bin/neo4j-import --into data/databases/graph.db --nodes /usr/local/lib/neo4j/importFile/expert.csv --nodes /usr/local/lib/neo4j/importFile/paper.csv --relationships /usr/local/lib/neo4j/importFile/expertPaper.csv

其中data/databases/graph.db必须不存在,nodes和relationships后面分别根生节点和关系的文件

等待结果即可。
遇到to many entries失败导致添加失败可以再加上 --bad-tolerance=10000修改 默认容错为1000

这样表示插入成功,开启neo4j即可使用。

neo4j_home$ ./bin/neo4j start

其它的Tips

  1. 在LOAD CSV前面加上USING PERIODIC COMMIT 1000,1000表示每1000行的数据进行一次Transaction提交,提升性能。
  2. 建立index可以使得查询性能得到巨大提升。如果不建立index,则需要对每个node的每一个属性进行遍历,所以比较慢。 并且index建立之后,新加入的数据都会自动编入到index中。 注意index是建立在label上的,不是在node上,所以一个node有多个label,需要对每一个label都建立index。
  3. 最后所有的困难都应该能在neo4j操作手册上得到官方 解答,点击下载阅读英文版。

转载于:https://my.oschina.net/zlb1992/blog/918243

发布了144 篇原创文章 · 获赞 37 · 访问量 20万+
展开阅读全文
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符

使用Python 语句将excel 自动导入本地Mysql数据表, 显示执行完毕,但Mysql 数据表中没有找到纪录

04-29

各位高手好: 在尝试着把之前自己的工作纪录导进本机建立的Mysql 数据库中 网上找到了某大神的代码: 如连接: https://www.cnblogs.com/longbigbeard/p/9309180.html 运行代码后显示运行成功,如图: ![图片说明](https://img-ask.csdn.net/upload/201904/29/1556513570_328017.png) 然而,当在MySQL 表格中复查的时候,发现数据库表格为空值(如图) ![图片说明](https://img-ask.csdn.net/upload/201904/29/1556513709_711636.png) 要导入的excel 表格截图如下:(好遗憾,似乎CSDN不能添加excel作为附件) ![图片说明](https://img-ask.csdn.net/upload/201904/29/1556514157_409812.png) 仿写代码如下:高手们知道问题出在那里么? ``` import xlrd import pymysql import xlrd # 打开excel---------------------------------------------------------- def open_excel(): try: book = xlrd.open_workbook('C:/Users/lenovo/Desktop/工作纪录就靠它了.xlsx') #文件名,把文件与py文件放在同一目录下 except: print("open excel file failed!") try: sheet = book.sheet_by_name('ANZ纪录') #execl里面的worksheet1 return sheet except: print("locate worksheet in excel failed!") # 验证:open_excel 是跑的通的 #----------------------------------------------------------------- #连接数据库------------------------------------------------------- try: db = pymysql.connect(host='localhost',user="root", passwd='QAZwsx12345678', db='test', charset='utf8') except: print("could not connect to mysql server") # 验证:本机数据库连接 是跑的通的 #---------------------------------------------------------------- def search_count(): cursor = db.cursor() select = "select count(PN) from pn_infor" #获取表中xxxxx记录数 cursor.execute(select) #执行sql语句 line_count = cursor.fetchone() print(line_count[0]) #验证:search_count 是可以跑通的 #----------------------------------------------------------------- def insert_deta(): sheet = open_excel() cursor = db.cursor() for i in range(5, sheet.nrows): #前5行是标题名,对应表中的字段名所以应该从第6行开始,计算机以0开始计数,所以值是6 inidate = sheet.cell(i,0).value #取第i行第0列 initiation_date = xlrd.xldate_as_datetime(inidate,0) # 把数字型的日期解码成真正的日期 requestor = sheet.cell(i,1).value#取第i行第1列,下面依次类推 EB = sheet.cell(i,2).value EOL_By = xlrd.xldate_as_datetime(EB,0) # 把数字型的日期解码成真正的日期 customer_name = sheet.cell(i,3).value Type_of_Service = sheet.cell(i,4).value PN = sheet.cell(i,5).value description30 = sheet.cell(i,6).value description80 = sheet.cell(i,7).value Enable = sheet.cell(i,8).value CostUSD = sheet.cell(i,9).value CostAUD = sheet.cell(i,10).value ListpriceAUD = sheet.cell(i,11).value DistipriceAUD = sheet.cell(i,12).value print(initiation_date) print(requestor) print(EOL_By) print(customer_name) print(Type_of_Service) print(PN) print(description30) print(description80) print(Enable) print(CostUSD) print(CostAUD) print(ListpriceAUD) print(DistipriceAUD) print("---------------") value = (initiation_date,requestor,EOL_By,customer_name,Type_of_Service,PN,description30,description80,Enable,CostUSD,CostAUD,ListpriceAUD,DistipriceAUD) print(value) sql = "INSERT INTO pn_infor(initiation_date,requestor,EOL_By,customer_name,Type_of_Service,PN,description30,description80,Enable,CostUSD,CostAUD,ListpriceAUD,DistipriceAUD)VALUES(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)" cursor.execute(sql,value) #执行sql语句 db.commit() cursor.close() #关闭连接 insert_deta() db.close()#关闭数据 print ("ok ") ``` 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览