title: Neo4j merge performance VS create/set
body: <p>I have a tree I store in Neo4j, in the tree, each node contains an identifier and a counter. I want to be able to increment that counter in a fast way, for a bunch of nodes.</p>
  
  <p>So I used MERGE (with ON CREATE SET and ON MATCH SET), however the performance is quite poor. And it seems that if I do it with two transactions, one to know if each node exists and another to create it or update it, it is faster.</p>
  
  <p>Do you know why MERGE is slower than a MATCH and CREATE combined ? And how can I improve its performance ?</p>
  
  <p>Here is a relevant example you can reproduce :</p>
  
  <pre><code>import datetime
  from py2neo import Graph
  
  def bench(query, count, reset=True):
      graph = Graph()
  
      if reset:
          graph.cypher.run("MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE n,r")
          graph.cypher.run("CREATE CONSTRAINT ON (node:Node) ASSERT node.number IS UNIQUE")
          graph.cypher.run("CREATE (r:Root)")
  
      start = datetime.datetime.now()
      tx = graph.cypher.begin()
      for i in range(count):
          tx.append(query, {'i': i})
      tx.commit()
  
      print('---')
      print('query : %s' % query)
      print("%i create. %s/second." % (count, count // (datetime.datetime.now() - start).total_seconds()))
  
  if __name__ == '__main__':
      bench("MATCH (:Root)-[:Child]-&gt;(n:Node {number: {i}}) RETURN n.count", 1000)
      bench("CREATE (:Root)-[:Child]-&gt;(:Node {number: {i}, count: 1})", 1000)
      bench("MATCH (root:Root) CREATE (root)-[:Child]-&gt;(:Node {number: {i}, count: 1})", 1000)
      bench("MATCH (root:Root) MERGE (root)-[:Child]-&gt;(n:Node {number: {i}}) ON CREATE SET n.count = 1 ON MATCH SET n.count = n.count + 1", 1000)
      bench("MATCH (root:Root)-[:Child]-&gt;(n:Node {number: {i}}) SET n.count = n.count + 1", 1000)
      bench("MATCH (root:Root) CREATE UNIQUE (root)-[:Child]-&gt;(n:Node {number: {i}}) SET n.count = coalesce(n.count, 0) + 1", 1000)
  </code></pre>
  
  <p>And the output of that code :</p>
  
  <pre><code>---
  query : MATCH (:Root)-[:Child]-&gt;(n:Node {number: {i}}) RETURN n.count
  1000 create. 1151.0/second.
  ---
  query : CREATE (:Root)-[:Child]-&gt;(:Node {number: {i}, count: 1})
  1000 create. 760.0/second.
  ---
  query : MATCH (root:Root) CREATE (root)-[:Child]-&gt;(:Node {number: {i}, count: 1})
  1000 create. 1092.0/second.
  ---
  query : MATCH (root:Root) MERGE (root)-[:Child]-&gt;(n:Node {number: {i}}) ON CREATE SET n.count = 1 ON MATCH SET n.count = n.count + 1
  1000 create. 218.0/second.
  ---
  query : MATCH (root:Root)-[:Child]-&gt;(n:Node {number: {i}}) SET n.count = n.count + 1
  1000 create. 3005.0/second.
  ---
  query : MATCH (root:Root) CREATE UNIQUE (root)-[:Child]-&gt;(n:Node {number: {i}}) SET n.count = coalesce(n.count, 0) + 1
  1000 create. 283.0/second.
  </code></pre>
  
  <p>Thanks for your help :)</p>