1

Here's the situation: I have a node that has a property ContactId which is set as unique and indexed. The node label is :Contact (node:Contact {ContactId:1})

I have another node similar to that pattern for Address: (node2:Address {AddressId:1})

I now try to add a new node that (among other properties, includes ContactId (for referencing)) (node3:ContactAddress {AddressId:1,ContactId:1})

When I run a merge command for each, the time for adding a node that contains a property that is set as unique in another node type seems to make the process much slower.

The ContactAddress node only contains relational properties between the Contact and Address nodes. Contact and Address nodes contain up to 10 properties each. Is this a bug, where Neo4j is check the property key -> value -> then node label?

Code and screenshot below:

string strForEach = string.Format("(n in {{{0}}} |  
MERGE (c:{1} {{{2} : n.{2}}}) SET c = n)", propKey, label, PK_Field);

var query = client
            .Cypher
            .ForEach(strForEach)
            .WithParam(propKey, entities.ToList());

Process timings

dcinzona
  • 477
  • 2
  • 14

1 Answers1

0

Constraint checks are more expensive than just inserts. They also take a global lock on the constraint to prevent multiple insertion.

I saw you don't use parameters, but string substitiution, I really recommend to change that and go with parameters.

Also setting the whole node c to n triggers constraint check again.

Your probably want to use the ON CREATE SET clause of MERGE

(n in {nodes} |  
MERGE (c:Label {key : n.key}}) ON CREATE SET c.foo = n.foo, c.bar = n.bar )
Michael Hunger
  • 41,339
  • 3
  • 57
  • 80
  • Thanks Michael. The params I'm using are for the list of items. I could add params for the labels and unique keys. Would the On Create function speed things up though? the entire point of merge, in this example, is I want to ALWAYS update the value based on the new list. So on create and on match, `set c = n`. The other issue is that the list is dynamic so getting the properties to set as in your example would be rather cumbersome...but if you think that will help with performance, I can give it a try. Do you know of any documentation anywhere that talks about this? – dcinzona Feb 24 '14 at 11:28
  • Also, keep in mind that the merge is also happening on the first two node types (contact and address), however those insert at about 1/second (which still kind of sucks), but when you look at the `Contact Address` node insertion, which contains both an indexed ContactId and AddressId key, it takes significantly longer. – dcinzona Feb 24 '14 at 11:30
  • Another quick question regarding your params comment, how can it be faster to have a second lookup for a label? What I mean is, how can this: `{labelName} -> parse Params for correct value -> lookup value in second param list` be faster than skipping that entire first param parsing step? I mean, in my head, there's no way that 2 lookups is faster than one, but then again, I'm REALLY new (obviously) to Neo4j. If the params lookup is faster than statically setting the string, awesome, I'll make that change. I just don't see how it would be. – dcinzona Feb 24 '14 at 11:52