Hi, The correction on the tx handling code fixed the problem so I dont exceed GC limit any more. Thank you very much! Is it more efficient to manipulate the properties in cypher queries or in java? I realised I have a lot of transitive relationship and it took a very long time to process. Also, usually how big should my batch be? I am currently using 1000 and it seems quite fast. Thanks.
On Friday, 13 May 2016 12:41:38 UTC+1, Cherie Pun wrote: > > Thanks for the advice! I will try it out and let you know how it goes. > > The stack overflow answer is here: > http://stackoverflow.com/questions/37126965/iterating-through-relationships-from-query-result-while-adding-new-relationship/37133192#37133192 > > So I just copied that part of the code and modified to suit my need. I > might have done some incorrect modification though. > > I really appreciate your help, thank you very much! > > Kind regards, > Cherie > On 13 May, 2016 12:38 pm, "'Michael Hunger' via Neo4j" < > neo4j@googlegroups.com> wrote: > >> Filter in cypher what you return, and yes only return the props needed >> >> For the batching you can also send in a list of maps on which you can >> store additional props or information. >> >> For concurrent execution neither guarantees uniqueness of rels but you >> execute one after another, so you have a guarantee with merge and create >> unique >> >> Where did you find that answer on SO? >> >> Von meinem iPhone gesendet >> >> Am 13.05.2016 um 13:31 schrieb Cherie Pun <cherie.cy....@gmail.com>: >> >> Hi, >> >> Thanks for the quick reply. I returned the relationship because the >> property of the transitive relationship that I am trying to create depends >> on the property of the original two relationship. Should I have just >> returned the properties and node id to reduce data? There are two different >> types of transitive relationship I want to create: 1) assign the property >> of bc to ac 2) assign the product of the trust strength of ab and bc to ac. >> >> The tx-handling code was written according to answers from stack overflow >> as I don't have much knowledge in batch executing cypher queries. Thanks >> for correcting it. >> >> I have read that merge does not guarantee uniqueness of relationship, so >> when should I use create unique and when I should I use merge? Thanks. >> >> Kind regards, >> Cherie >> On 13 May, 2016 12:16 pm, "'Michael Hunger' via Neo4j" < >> neo4j@googlegroups.com> wrote: >> >> >> Your tx-handling code looks wrong. >> >> You should execute the whole batch of creating the connections in the >> other thread, Just grabbing the transaction there is very dangerous as the >> tx will be used that's attached to the current thread instead. >> >> I also recommend batching in cypher, that makes it much easier: >> Just send in a batch (e.g. 100k) list of pairs of id's as parameters and >> then do >> >> pool.submit( () -> >> Iterables.<Long>singleOrNull(db.execute(" >> UNWIND {data} as pair >> MATCH (a),(b) WHERE id(a) = pair[0] and id(b) = pair[1] >> MERGE (a)-[:TRUST]->(b) RETURN count(*) as c; >> ", batchOfIds()).columnAs("c")); >> )).get() >> >> If your return ab, bc then that's relationships? but in the other query >> you match nodes? >> >> You should only return id(a),id(c) to minimize the data created. >> >> >> > Am 13.05.2016 um 12:49 schrieb Cherie Pun <cherie.cy....@gmail.com>: >> > >> > Hi, >> > >> > Thanks for your reply. By actual code do you mean all my files that are >> related? I have attached the main part of the code that does the querying >> underneath the stacktrace. The other files just defined strings for the >> property names and enum type for relationship and node. >> > >> > The query that I ran first was : >> > private final String FIND_TRANSITIVE_RELATION_QUERY = >> > "MATCH (a:" + TwitterLabels.USERS + ") " + >> > "- [ab:" + TwitterRelationships.TRUST + "] -> " + >> > "(b:" + TwitterLabels.USERS + ") " + >> > "- [bc:" + TwitterRelationships.TRUST + "] -> " + >> > "(c:" + TwitterLabels.USERS + ")\n" + >> > "WHERE a <> c\n" + >> > "return ab, bc"; >> > Iterating through the result from the query, I then perform a another >> query that create a unique trust relationship between node a and c: >> > private final String CREATE_UNIQUE_TRUST_RELATION_QUERY = >> > "MATCH (a:" + TwitterLabels.USERS + "),(b:" + >> TwitterLabels.USERS + ")\n" + >> > "WHERE id(a) = {startNode} AND id(b) = {endNode} \n" + >> > "CREATE UNIQUE (a) - [r:" + TwitterRelationships.TRUST >> + "] -> (b) \n" + >> > "return r"; >> > >> > The second query is being executed on another thread, and the thread >> commits the transaction for every 1000 queries. >> > >> > This executes fine until it processed 200,000 result and crashes >> because of gc limit reached. I did a heap dump and found out that the >> relationshipproxy objects were taking up most of the space. >> > >> > I hope that gives you sufficient information, please let me know if you >> need more explanation of my code. >> > >> > Kind regards, >> > Cherie >> > >> > >> > Can you share your actual code and queries >> > >> > Von meinem iPhone gesendet >> > >> > Am 12.05.2016 um 18:52 schrieb Cherie Pun <cherie.cy....@gmail.com>: >> > >> > > I am trying to iterate through the results from the first query and >> execute an extra cypher query for each result to either create or find the >> existing relationship. However I encountered GC overhead error and the >> stack trace is as followed. I thought running the queries in batch of 100 >> will solve the memory problem but it seems that either it's using up the >> memory too quickly or not releasing the memory quick enough. It broke down >> after processing 200000 queries after I increased the batch size to 1000. >> Is there a way to optimise my query to reduce the memory used, or is there >> an alternative way to achieve the same result? Thanks. >> > > >> > > Exception in thread "main" java.lang.OutOfMemoryError: GC overhead >> limit exceeded >> > > at >> scala.collection.mutable.OpenHashMap.foreachUndeletedEntry(OpenHashMap.scala:226) >> > > at >> scala.collection.mutable.OpenHashMap.foreach(OpenHashMap.scala:219) >> > > at >> org.neo4j.cypher.internal.compiler.v2_3.ExecutionContext.foreach(ExecutionContext.scala:46) >> > > at >> scala.collection.TraversableOnce$class.foldLeft(TraversableOnce.scala:155) >> > > at >> org.neo4j.cypher.internal.compiler.v2_3.ExecutionContext.foldLeft(ExecutionContext.scala:33) >> > > at >> org.neo4j.cypher.internal.frontend.v2_3.helpers.Eagerly$.mapToBuilder(Eagerly.scala:44) >> > > at >> org.neo4j.cypher.internal.frontend.v2_3.helpers.Eagerly$.immutableMapValues(Eagerly.scala:37) >> > > at >> org.neo4j.cypher.internal.compiler.v2_3.ClosingIterator$$anonfun$next$1.apply(ResultIterator.scala:76) >> > > at >> org.neo4j.cypher.internal.compiler.v2_3.ClosingIterator$$anonfun$next$1.apply(ResultIterator.scala:72) >> > > at >> org.neo4j.cypher.internal.compiler.v2_3.ClosingIterator$$anonfun$failIfThrows$1.apply(ResultIterator.scala:121) >> > > at >> org.neo4j.cypher.internal.compiler.v2_3.ClosingIterator.decoratedCypherException(ResultIterator.scala:130) >> > > at >> org.neo4j.cypher.internal.compiler.v2_3.ClosingIterator.failIfThrows(ResultIterator.scala:119) >> > > at >> org.neo4j.cypher.internal.compiler.v2_3.ClosingIterator.next(ResultIterator.scala:72) >> > > at >> org.neo4j.cypher.internal.compiler.v2_3.ClosingIterator.next(ResultIterator.scala:50) >> > > at >> org.neo4j.cypher.internal.compiler.v2_3.PipeExecutionResult.next(PipeExecutionResult.scala:77) >> > > at >> org.neo4j.cypher.internal.compiler.v2_3.PipeExecutionResult$$anon$2.next(PipeExecutionResult.scala:70) >> > > at >> org.neo4j.cypher.internal.compiler.v2_3.PipeExecutionResult$$anon$2.next(PipeExecutionResult.scala:68) >> > > at >> org.neo4j.cypher.internal.compatibility.ExecutionResultWrapperFor2_3$$anon$1$$anonfun$next$1.apply(CompatibilityFor2_3.scala:234) >> > > at >> org.neo4j.cypher.internal.compatibility.ExecutionResultWrapperFor2_3$$anon$1$$anonfun$next$1.apply(CompatibilityFor2_3.scala:234) >> > > at >> org.neo4j.cypher.internal.compatibility.exceptionHandlerFor2_3$.runSafely(CompatibilityFor2_3.scala:116) >> > > at >> org.neo4j.cypher.internal.compatibility.ExecutionResultWrapperFor2_3$$anon$1.next(CompatibilityFor2_3.scala:234) >> > > at >> org.neo4j.cypher.internal.compatibility.ExecutionResultWrapperFor2_3$$anon$1.next(CompatibilityFor2_3.scala:229) >> > > at >> org.neo4j.cypher.javacompat.ExecutionResult.next(ExecutionResult.java:233) >> > > at >> org.neo4j.cypher.javacompat.ExecutionResult.next(ExecutionResult.java:55) >> > > at java.util.Iterator.forEachRemaining(Iterator.java:116) >> > > at >> Neo4j.TrustCalculator.iterateAndExecuteBatchedInSeparateThread(TrustCalculator.java:239) >> > > at >> Neo4j.TrustCalculator.insertSimpleTransitiveTrust(TrustCalculator.java:127) >> > > at Neo4j.TrustCalculator.main(TrustCalculator.java:265) >> > > at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) >> > > at >> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) >> > > at >> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) >> > > at java.lang.reflect.Method.invoke(Method.java:483) >> > > >> > > private final String CREATE_UNIQUE_TRUST_RELATION_QUERY = >> > > "MATCH (a:" + TwitterLabels.USERS + "),(b:" + >> TwitterLabels.USERS + ")\n" + >> > > "WHERE id(a) = {startNode} AND id(b) = {endNode} \n" + >> > > "CREATE UNIQUE (a) - [r:" + >> TwitterRelationships.TRUST + "] -> (b) \n" + >> > > "return r"; >> > > >> > > private final String FIND_TRANSITIVE_RELATION_QUERY = >> > > "MATCH (a:" + TwitterLabels.USERS + ") " + >> > > "- [ab:" + TwitterRelationships.TRUST + "] -> " + >> > > "(b:" + TwitterLabels.USERS + ") " + >> > > "- [bc:" + TwitterRelationships.TRUST + "] -> " + >> > > "(c:" + TwitterLabels.USERS + ")\n" + >> > > "WHERE a <> c\n" + >> > > "return ab, bc"; >> > > >> > > private ExecutorService createSinglePool() { >> > > return Executors.newSingleThreadExecutor(); >> > > } >> > > >> > > private void iterateAndExecuteBatchedInSeparateThread(int batchsize, >> Iterator iterator, Consumer consumer) { >> > > final int[] opsCount = {0}; >> > > final int[] batchesCount = {0}; >> > > ExecutorService executorService = createSinglePool(); >> > > try { >> > > final Transaction[] workerTransaction = >> {executorService.submit(() -> graphDb.beginTx()).get()}; >> > > >> > > iterator.forEachRemaining(t -> executorService.submit(() -> { >> > > consumer.accept(t); >> > > if ((++opsCount[0]) % batchsize == 0) { >> > > batchesCount[0]++; >> > > workerTransaction[0].success(); >> > > workerTransaction[0].close(); >> > > workerTransaction[0] = graphDb.beginTx(); >> > > } >> > > })); >> > > executorService.submit(() -> { >> > > workerTransaction[0].success(); >> > > workerTransaction[0].close(); >> > > }).get(); >> > > >> > > } catch (InterruptedException | ExecutionException e) { >> > > throw new RuntimeException(e); >> > > } >> > > } >> > > >> > > >> > > public void insertSimpleTransitiveTrust(){ >> > > try ( Transaction tx = graphDb.beginTx() ) >> > > { >> > > Result results = graphDb.execute( >> FIND_TRANSITIVE_RELATION_QUERY, new HashMap<String, Object>() ); >> > > >> > > iterateAndExecuteBatchedInSeparateThread(1000, results, >> result-> insertOneSimpleTransitiveTrust((Map<String, Object>) result)); >> > > >> > > tx.success(); >> > > } >> > > } >> > > >> > > private void insertOneSimpleTransitiveTrust(Map<String, Object> map){ >> > > Object object = map.get("ab"); >> > > Relationship trustAb = (Relationship) object; >> > > object = map.get("bc"); >> > > Relationship trustBc = (Relationship) object; >> > > if(trustAb.hasProperty(TwitterProperties.CONVERSATIONAL_TRUST) && >> trustBc.hasProperty(TwitterProperties.CONVERSATIONAL_TRUST)){ >> > > Node nodeA = trustAb.getStartNode(); >> > > Node nodeB = trustAb.getEndNode(); >> > > Node nodeC = trustBc.getEndNode(); >> > > >> > > Map<String, Object> params = new HashMap<String, Object>(); >> > > params.put("startNode", nodeA.getId()); >> > > params.put("endNode", nodeC.getId()); >> > > Result results = graphDb.execute( >> CREATE_UNIQUE_TRUST_RELATION_QUERY, params ); >> > > if(results.hasNext()){ >> > > Map<String, Object> result = results.next(); >> > > object = result.get("r"); >> > > Relationship transitiveTrust = (Relationship) object; >> > > >> transitiveTrust.setProperty(TwitterProperties.SIMPLE_TRANSITIVE_TRUST, >> trustBc.getProperty(TwitterProperties.CONVERSATIONAL_TRUST)); >> > > } >> > > } >> > > } >> > > >> > > >> > > >> > > -- >> > > You received this message because you are subscribed to the Google >> Groups "Neo4j" group. >> > > To unsubscribe from this group and stop receiving emails from it, >> send an email to neo4j+unsubscr...@googlegroups.com. >> > > For more options, visit https://groups.google.com/d/optout. >> > >> > -- >> > You received this message because you are subscribed to a topic in the >> Google Groups "Neo4j" group. >> > To unsubscribe from this topic, visit >> https://groups.google.com/d/topic/neo4j/sjFDz496AwA/unsubscribe. >> > To unsubscribe from this group and all its topics, send an email to >> neo4j+unsubscr...@googlegroups.com. >> > For more options, visit https://groups.google.com/d/optout. >> > >> > -- >> > You received this message because you are subscribed to the Google >> Groups "Neo4j" group. >> > To unsubscribe from this group and stop receiving emails from it, send >> an email to neo4j+unsubscr...@googlegroups.com. >> > For more options, visit https://groups.google.com/d/optout. >> >> -- >> You received this message because you are subscribed to a topic in the >> Google Groups "Neo4j" group. >> To unsubscribe from this topic, visit >> https://groups.google.com/d/topic/neo4j/sjFDz496AwA/unsubscribe. >> To unsubscribe from this group and all its topics, send an email to >> neo4j+unsubscr...@googlegroups.com. >> For more options, visit https://groups.google.com/d/optout. >> >> -- >> You received this message because you are subscribed to the Google Groups >> "Neo4j" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to neo4j+unsubscr...@googlegroups.com. >> For more options, visit https://groups.google.com/d/optout. >> >> -- >> You received this message because you are subscribed to a topic in the >> Google Groups "Neo4j" group. >> To unsubscribe from this topic, visit >> https://groups.google.com/d/topic/neo4j/sjFDz496AwA/unsubscribe. >> To unsubscribe from this group and all its topics, send an email to >> neo4j+unsubscr...@googlegroups.com. >> For more options, visit https://groups.google.com/d/optout. >> > -- You received this message because you are subscribed to the Google Groups "Neo4j" group. To unsubscribe from this group and stop receiving emails from it, send an email to neo4j+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.