2019-06-28 Neo4j 导入数据的几种方式对比

1. 遇到的问题

在使用Neo4j时遇到一个问题,需要导入上百亿数据(同时导入节点和关系),想找一个最合适的方案来导入数据。于是就想测测各种导入方式的效率以及成本。

2. 常见数据导入方式概览

(1) Cypher create 语句,为每一条数据写一个create

(2) Cypher load csv 语句,将数据转成CSV格式,通过LOAD CSV读取数据。

(3) 官方提供的neo4j-import工具,未来将被neo4j-adminimport代替

(4) 官方提供的Java API    BatchInserter

(5) 大牛编写的 batch-import 工具

(6) neo4j-apocload.csv +apoc.load.relationship

(7) 针对实际业务场景,定制化开发

这些工具有什么不同呢?速度如何?适用的场景分别是什么?


figure1 各种数据导入方式对比

注释:本次测试使用的id(不是Neo4j id)类型是String,为uuid,如果同一Label下数据不超过2^32,可以用int类型


3. 各种导入方法实际测试

3.1  create

未测试。

批量插入语句

./bin/neo4j-shell-c < /data/stale/data01/neo4j/neo4j_script.cypher

 ./bin/neo4j-shell  -path ./data/dbms/  -conf ./conf/neoo4j.conf  -file create_index.cypther

3.2  load csv

load csv 不能动态传Label、RelationShip,所以测试时Label、RelationShip是写死的

数据格式

uuid,name,Label

b6b0ea842890425588d4d3cfb38139a9,"文烁",Label1

5099c4f943d94fa1873165e3f6f3c2fb,"齐贺喜",Label3

c83ed0ae9fb34baa956a42ecf99c8f6e,"李雄",Label2

e62d1142937f4de994854fa1b3f0670a,"房玄龄",Label


3.2.1 导入10w节点


neo4j-sh (?)$ using periodic commit 10000 load csv with headers from "file:/data/stale/data01/neo4j/node_uuid_10w.csv" as line with line create (:Test {uuid:line.uuid, name:line.name});

+-------------------+

| No data returned. |

+-------------------+

Nodes created: 100000

Properties set: 200000

Labels added: 100000

3412 ms

10万数据(只有节点,没有关系)导入用时3.412s

3.2.2 导入1kw节点

neo4j-sh (?)$ load csv from "file:/data/stale/data01/neo4j/node_uuid_1kw.csv" as line return count(*);

+----------+

| count(*) |

+----------+

| 10000010 |

+----------+

1 row

7434 ms

neo4j-sh (?)$ using periodic commit 10000 load csv with headers from "file:/data/stale/data01/neo4j/node_uuid_1kw.csv" as line with line create (:Test {uuid:line.uuid, name:line.name});

+-------------------+

| No data returned. |

+-------------------+

Nodes created: 10000009

Properties set: 20000018

Labels added: 10000009

151498 ms

1千万数据(只有节点,没有关系)导入用时151.498s

3.2.3 导入100w关系


neo4j-sh (?)$ using periodic commit 100000 load csv with headers from "file:/data/stale/data01/neo4j/relathionship_uuid_100w.csv" as line with line merge (n1:Test {uuid:line.uuid1}) merge (n2:Test {uuid:line.uuid2}) with * create (n1)-[r:Relationship]->(n2);

+-------------------+

| No data returned. |

+-------------------+

Relationships created: 1000000

75737 ms

创建100w关系用时75.737s

因为我节点已经提前导入了,所以merge的时候节点全部存在,根据结果可以看到,只创建了100w关系,没有创建节点

但是这种方式有一个弊端,关系要写死,在只有一种关系时试用,在有多种关系时,不适用。还有一个不好的地方就是用的merge,uuid是String类型,会随着数据的正常速度变慢。

load csv 的速度我用的是导入节点时间+导入关系时间

导入100w 节点+数据 (Label写死,RelationShip写死,也就是只有一种Label和一种RelationShip) 共花费15.149 + 75.737 = 90.886 。load csv的速度大概在1.1w/s,但这种情况一般很少使用,仅供参考。

3.3  neo4j-import

3.3.1 数据格式

node.csv

uuid:ID(users),name:String,:Label

c63bc1e7dc594fd49fbe36dd664ff0a6,"

维特",Label1

b52fb5f2266b4edbadc82b5ec4c430b8,"廖二松",Label2

d95d430cfeee47dd95f9bf5e0ec1ae93,"徐青偏",Label3

b2d1fffc8173461fa603d4fbb601b3ee,"杨础维",Label2


relationship.csv

uuid:START_ID(users),uuid:END_ID(users),:TYPE

c63bc1e7dc594fd49fbe36dd664ff0a6,b2d1fffc8173461fa603d4fbb601b3ee,RelationShip1

d95d430cfeee47dd95f9bf5e0ec1ae93,c63bc1e7dc594fd49fbe36dd664ff0a6,RelationShip2

b2d1fffc8173461fa603d4fbb601b3ee,b52fb5f2266b4edbadc82b5ec4c430b8,RelationShip3

b52fb5f2266b4edbadc82b5ec4c430b8,d95d430cfeee47dd95f9bf5e0ec1ae93,RelationShip1

3.3.2 导入1000w数据

IMPORT DONE in 27s 932ms.

Imported:

10000000 nodes

10000000 relationships

20000000 properties

Peak memory usage: 209.81 MB

空库初始化导入1千万数据(1kw节点 1kw关系 2kw属性,id使用integer,属性中只有数字和英文)花费27s 932ms

3.3.3 导入1000w数据

IMPORT DONE in 1m 50s 9ms.

Imported:

10000000 nodes

10000000 relationships

20000000 properties

Peak memory usage: 209.81 MB

空库初始化导入1千万数据(1kw节点 1kw关系 2kw属性,包含中文属性)花费1min 50s 9ms

3.3.4 导入1.1y数据

IMPORT DONE in 15m 9s 37ms.

Imported:

110000010 nodes

110000000 relationships

220000020 properties

Peak memory usage: 2.27 GB

There were bad entries which were skipped and logged into /data/stale/data01/neo4j/neo4j-community-3.1.0/data/databases/test_uuid_1y_graph.db/bad.log

空库初始化导入1.1亿数据(1.1亿节点 1.1关系 2.2亿属性)花费15min 9s 37ms

3.4  BatchInster

batch-import调的BatchInserter的代码,所以BatchInserter没测,可以认为BatchInster和batch-import速度一样

3.5  batch-import

数据格式

node.csv

uuid:string:users,name:String,:label

c63bc1e7dc594fd49fbe36dd664ff0a6,"

维特",Label1

b52fb5f2266b4edbadc82b5ec4c430b8,"廖二松",Label2

d95d430cfeee47dd95f9bf5e0ec1ae93,"徐青偏",Label3

b2d1fffc8173461fa603d4fbb601b3ee,"杨础维",Label2


relationship.csv

uuid:string:users,uuid:string:users,type

c63bc1e7dc594fd49fbe36dd664ff0a6,b2d1fffc8173461fa603d4fbb601b3ee,RelationShip1

d95d430cfeee47dd95f9bf5e0ec1ae93,c63bc1e7dc594fd49fbe36dd664ff0a6,RelationShip2

b2d1fffc8173461fa603d4fbb601b3ee,b52fb5f2266b4edbadc82b5ec4c430b8,RelationShip3

b52fb5f2266b4edbadc82b5ec4c430b8,d95d430cfeee47dd95f9bf5e0ec1ae93,RelationShip1

Using: Importer batch.properties /data/stale/data01/neo4j/neo4j-community-3.1.0/data/databases/test_uuid_1000w_graph.db /data/stale/data01/neo4j/node_uuid_100w.csv /data/stale/data01/neo4j/relationship_uuid_100w.csv

Using Existing Configuration File

..........

Importing 1000000 Nodes took 15 seconds

..........

Importing 1000000 Relationships took 16 seconds

Total import time: 92 seconds


在数据库中已有1kw数据的情况下,导入100w数据(100w节点 100w关系 200w属性,包含中文属性)花费92s



3.6  apoc

load csv + merge + apoc.create.relationship


neo4j-sh (?)$ using periodic commit 1000000

> load csv from 'file:/data/stale/data01/neo4j/relathionship_uuid_1kw.csv' as line fieldterminator ','

> merge (n1:Test {uuid: line[0]})

> merge (n2:Test {uuid: line[1]})

> with n1, n2, line

> CALL apoc.create.relationship(n1, line[2], {}, n2) YIELD rel

> return count(rel) ;

+------------+

| count(rel) |

+------------+

| 10000010   |

+------------+

1 row

Nodes created: 8645143

Properties set: 8645143

Labels added: 8645143

2395852 ms


在1.1亿数据上增量更新1kw数据花费2395.852s

VIRT Memory 90G RES Memory 78G


因为这部分也用到merge了,数据量越大,速度越慢


4. 结论


根据实际情况选用最好的方式

(1)  neo4j-import导入速度快,但是要求是空库,导入时要停止neo4j,也就是脱机导入,而且你要提前处理好数据,数据最好不要有重复,如果有重复,可以导入时跳过,然后根据bad.log来查看或者修正这部分数据

(2)  batch-import可以增量导入,但是要求导入时停止neo4j数据库(脱机导入),而且增量更新的数据不会和库里存在的数据对比,所以要求数据全是新的,否则会出现重复数据

(3)  load csv比较通用,而且可以在neo4j数据库运行时导入,但是导入速度相对较慢,要提前整理好数据,而且不能动态创建 Label RelationShip

(4) apoc挺好用的,可以动态创建Label、RelationShip,但是速度一般.


转载文献:https://mp.weixin.qq.com/s/ZYqDSx333nTCYBpHydfYMg

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容