Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cypher - Query Optimization

My question is why WHERE operator is not working as fast as expected? Consider I have 7 nodes with label Consumer. Here is some sample data...

MERGE (c:Consumer {mobileNumber: "000000000000"})
MERGE (:Consumer {mobileNumber: "111111111111"})
MERGE (:Consumer {mobileNumber: "222222222222"})
MERGE (:Consumer {mobileNumber: "333333333333"})
MERGE (:Consumer {mobileNumber: "444444444444"})
MERGE (:Consumer {mobileNumber: "555555555555"})
MERGE (:Consumer {mobileNumber: "666666666666"})
WITH c
MATCH (c1:Consumer) WHERE c1.mobileNumber <> "000000000000"
MERGE (c)-[:HAS_CONTACT]->(c1)

And there is a HAS_CONTACT relationship in between :Consumer(mobileNumber:{"000000000000"}) and all other 6 nodes. Also there is a unique index constraint on mobileNumber field. Now when I try to execute below query:

    PROFILE MATCH (n:Consumer{mobileNumber : "000000000000"}),
    (m:Consumer{mobileNumber : "111111111111"}) 
    WITH n,m 
    MATCH path = SHORTESTPATH((n)-[contacts:HAS_CONTACT]-(m)) 
    RETURN contacts;

So its working fine as expected(Search nodes on the basis of unique index). Below is its result: Without Where clause

Now let change above query using WHERE clause:

PROFILE MATCH (n:Consumer{mobileNumber : "000000000000"}),
(m:Consumer) WHERE m.mobileNumber 
IN (["111111111111"]) 
WITH n,m 
MATCH path = SHORTESTPATH((n)-[contacts:HAS_CONTACT]-(m)) 
RETURN contacts;

Query Result: With WHERE clause

Now although above query is working fine, and giving same result as that of old one. But for endNode where I have used WHERE clause, it doesn't uses any indexes. It first searches for all existing nodes, and then filter result using WHERE clause, which can be too expensive if there are hundreds of thousands of nodes with same label.

So my Questions are:

  1. Why it doesn't uses indexes when I use WHERE clause?
  2. What is the best way to refer multiple nodes with less number of db hits?
  3. Can I use IN operator while expecting index search?
like image 895
Afridi Avatar asked Jul 24 '17 07:07

Afridi


1 Answers

As @DaveBennett said, this problem does not seem to exist in version 3.2.2.

If you are using a prior version, try providing hints to the planner that it should use indexing:

PROFILE MATCH
  (n:Consumer{mobileNumber : "000000000000"}),
  (m:Consumer)
USING INDEX n:Consumer(mobileNumber)
USING INDEX m:Consumer(mobileNumber)
WHERE m.mobileNumber  IN (["111111111111"])
MATCH path = SHORTESTPATH((n)-[contacts:HAS_CONTACT]-(m))
RETURN contacts;

This might also work, since some planners seem to automatically attempt to use indexing on (only) the first MATCH term:

PROFILE MATCH
  (n:Consumer{mobileNumber : "000000000000"}),
  (m:Consumer)
USING INDEX m:Consumer(mobileNumber)
WHERE m.mobileNumber  IN (["111111111111"])
MATCH path = SHORTESTPATH((n)-[contacts:HAS_CONTACT]-(m))
RETURN contacts;
like image 109
cybersam Avatar answered Sep 30 '22 12:09

cybersam