Current Neo4J documentation states that to create a relationship, both nodes are locked.
Now consider one node be a master node and all other nodes being created are to be related to it. For example, all new "Animal" nodes need to be related to a master "Zoo" node.
So, when a lot of new "Animal" nodes are being created with relationship to existing "Zoo" node, wouldn't all Cypher requests just queue up waiting on the lock ? Because every request needs to lock the "Zoo" node.
I'm observing slow downs when a lot of data is being created on a graph in this manner.
Is there a way to tell Neo4J to not lock the nodes for a Cypher CREATE request ? Can some sort of parallel writes be enabled ?
Update :
Test Results:
Create Zoo nodes: time taken (ms): 2222
Create Animal nodes for separate Zoos: time taken (ms): 2206
Create Animal nodes for same Zoo: time taken (ms): 9015
There is a difference of about 7 seconds for just 200 simultaneous queries.
Test Script (using NodeJS Driver, neo4j version 2.2.4, ubuntu linux):
- NodeJS Driver
- Neo4j version 2.2.4, community edition
- Ubuntu Linux
var seraph = require('seraph');
var moment = require('moment');
var async = require('async');
var neo4j = seraph({
"url": "http://localhost:7474",
"user": "neo4j",
"pass": "neo4j"
});
var num = 200;
async.series([
function (cb) {
// clean
neo4j.query('MATCH (n:Zoo)-[r:HAS]->(a:Animal) DELETE n,r,a', cb);
},
function (cb) {
// clean
neo4j.query('MATCH (n:Zoo) DELETE n', cb);
},
function (cb) {
// we create Zoo nodes, each with a num property
var start = moment();
var count = 0;
var abort = false;
for (var i = 0; i < num; i++) {
neo4j.query('CREATE (n:Zoo {obj})', { obj: { num: i } }, function (err, nodes) {
if (err) {
cb(err);
abort = true;
} else {
count++;
if (count >= num && !abort) {
console.log('Create Zoo nodes: time taken (ms): ' + moment().diff(start));
cb();
}
}
});
}
},
function (cb) {
// we create (Zoo)-[HAS]->(Animal) nodes, each Animal node related with a SEPARATE Zoo node
var start = moment();
var count = 0;
var abort = false;
for (var i = 0; i < num; i++) {
neo4j.query('MATCH (n:Zoo) WHERE n.num = {num} CREATE (n)-[r:HAS]->(a:Animal) RETURN a LIMIT 1', { num: i }, function (err, nodes) {
if (err) {
cb(err);
abort = true;
} else {
count++;
if (count >= num && !abort) {
console.log('Create Animal nodes for separate Zoos: time taken (ms): ' + moment().diff(start));
cb();
}
}
});
}
},
function (cb) {
// we create (Zoo)-[HAS]->(Animal) nodes, each Animal node related with SAME Zoo node
var start = moment();
var count = 0;
var abort = false;
for (var i = 0; i < num; i++) {
neo4j.query('MATCH (n:Zoo) WHERE n.num = 0 CREATE (n)-[r:HAS]->(a:Animal) RETURN a LIMIT 1', function (err, nodes) {
if (err) {
cb(err);
abort = true;
} else {
count++;
if (count >= num && !abort) {
console.log('Create Animal nodes for same Zoo: time taken (ms): ' + moment().diff(start));
cb();
}
}
});
}
}
], function (err) {
if (err) {
console.error(err);
}
process.exit(0);
});