10.8. Using

USING is used to influence the decisions of the planner when building an execution plan for a query. NOTE: Forcing planner behaviour is an advanced feature, and should be used with caution by experienced developers and/or database administrators only, as it may cause queries to perform poorly.

When executing a query, Neo4j needs to decide where in the query graph to start matching. This is done by looking at the MATCH clause and the WHERE conditions and using that information to find useful indexes.

This index might not be the best choice though — sometimes multiple indexes could be used, and Neo4j has picked the wrong one (from a performance point of view).

You can force Neo4j to use a specific starting point through the USING clause. This is called giving an index hint.

If your query matches large parts of an index, it might be faster to scan the label and filter out nodes that do not match. To do this, you can use USING SCAN. It will force Cypher to not use an index that could have been used, and instead do a label scan.

[Note]Note

You cannot use index hints if your query has a START clause.

You can also force Neo4j to produce plans which perform joins between query sub-graphs.

Query using an index hint

To query using an index hint, use USING INDEX.

Query 

MATCH (n:Swede)
USING INDEX n:Swede(surname)
WHERE n.surname = 'Taylor'
RETURN n

Query Plan 

+-----------------+----------------+------+---------+-------------+-----------------+
| Operator        | Estimated Rows | Rows | DB Hits | Identifiers | Other           |
+-----------------+----------------+------+---------+-------------+-----------------+
| +ProduceResults |              1 |    1 |       0 | n           | n               |
| |               +----------------+------+---------+-------------+-----------------+
| +NodeIndexSeek  |              1 |    1 |       2 | n           | :Swede(surname) |
+-----------------+----------------+------+---------+-------------+-----------------+

Total database accesses: 2

Query using multiple index hints

To query using multiple index hints, use USING INDEX.

Query 

MATCH (m:German)-->(n:Swede)
USING INDEX m:German(surname)
USING INDEX n:Swede(surname)
WHERE m.surname = 'Plantikow' AND n.surname = 'Taylor'
RETURN m

Query Plan 

+-------------------+------+---------+----------------+----------------+
| Operator          | Rows | DB Hits | Identifiers    | Other          |
+-------------------+------+---------+----------------+----------------+
| +ColumnFilter     |    1 |       0 | m              | keep columns m |
| |                 +------+---------+----------------+----------------+
| +TraversalMatcher |    1 |      11 | anon[17], m, n | n, anon[17], m |
+-------------------+------+---------+----------------+----------------+

Total database accesses: 11

Hinting a label scan

If the best performance is to be had by scanning all nodes in a label and then filtering on that set, use USING SCAN.

Query 

MATCH (m:German)
USING SCAN m:German
WHERE m.surname = 'Plantikow'
RETURN m

Query Plan 

+------------------+----------------+------+---------+-------------+------------------------------+
| Operator         | Estimated Rows | Rows | DB Hits | Identifiers | Other                        |
+------------------+----------------+------+---------+-------------+------------------------------+
| +ProduceResults  |              1 |    1 |       0 | m           | m                            |
| |                +----------------+------+---------+-------------+------------------------------+
| +Filter          |              1 |    1 |       1 | m           | m.surname == {  AUTOSTRING0} |
| |                +----------------+------+---------+-------------+------------------------------+
| +NodeByLabelScan |              1 |    1 |       2 | m           | :German                      |
+------------------+----------------+------+---------+-------------+------------------------------+

Total database accesses: 3

Hinting a join on a single node

To force the query planner to produce plans with joins in them, use USING JOIN.

Query 

MATCH (andres { name:'Andres' })-->(x)<--(emil { name: 'Emil' })
USING JOIN ON x
RETURN x

Query Plan 

+-----------------+----------------+------+---------+-------------------------------------+---------------------------------------------------------------------------+
| Operator        | Estimated Rows | Rows | DB Hits | Identifiers                         | Other                                                                     |
+-----------------+----------------+------+---------+-------------------------------------+---------------------------------------------------------------------------+
| +ProduceResults |              0 |    1 |       0 | x                                   | x                                                                         |
| |               +----------------+------+---------+-------------------------------------+---------------------------------------------------------------------------+
| +Filter         |              0 |    1 |       6 | anon[31], anon[37], andres, emil, x | Ands(Fby(NOT(anon[31] == anon[37]),Last(andres.name == {  AUTOSTRING0}))) |
| |               +----------------+------+---------+-------------------------------------+---------------------------------------------------------------------------+
| +Expand(All)    |              2 |    9 |      12 | anon[31], anon[37], andres, emil, x | (x)<--(andres)                                                            |
| |               +----------------+------+---------+-------------------------------------+---------------------------------------------------------------------------+
| +NodeHashJoin   |              1 |    3 |       0 | anon[37], emil, x                   | x                                                                         |
| |\              +----------------+------+---------+-------------------------------------+---------------------------------------------------------------------------+
| | +AllNodesScan |              5 |    5 |       6 | x                                   |                                                                           |
| |               +----------------+------+---------+-------------------------------------+---------------------------------------------------------------------------+
| +Expand(All)    |              1 |    3 |       4 | anon[37], emil, x                   | (emil)-->(x)                                                              |
| |               +----------------+------+---------+-------------------------------------+---------------------------------------------------------------------------+
| +Filter         |              1 |    1 |       5 | emil                                | emil.name == {  AUTOSTRING1}                                              |
| |               +----------------+------+---------+-------------------------------------+---------------------------------------------------------------------------+
| +AllNodesScan   |              5 |    5 |       6 | emil                                |                                                                           |
+-----------------+----------------+------+---------+-------------------------------------+---------------------------------------------------------------------------+

Total database accesses: 39

Hinting a join on multiple nodes

To force the query planner to produce plans with joins in them, use USING JOIN.

Query 

MATCH (andres { name:'Andres' })-[r1]->(x)<-[r2]-(y)-[r3]-(andres)
USING JOIN ON x, y
RETURN x, y

Query Plan 

+-----------------+----------------+------+---------+--------------------------+----------------------------------------------+
| Operator        | Estimated Rows | Rows | DB Hits | Identifiers              | Other                                        |
+-----------------+----------------+------+---------+--------------------------+----------------------------------------------+
| +ProduceResults |              1 |    3 |       0 | x, y                     | x, y                                         |
| |               +----------------+------+---------+--------------------------+----------------------------------------------+
| +Filter         |              1 |    3 |       0 | andres, r1, r2, r3, x, y | Ands(Fby(NOT(r1 == r2),Last(NOT(r2 == r3)))) |
| |               +----------------+------+---------+--------------------------+----------------------------------------------+
| +NodeHashJoin   |              1 |    3 |       0 | andres, r1, r2, r3, x, y | x, y                                         |
| |\              +----------------+------+---------+--------------------------+----------------------------------------------+
| | +Expand(All)  |             10 |   10 |      15 | r2, x, y                 | (y)-[r2:]->(x)                               |
| | |             +----------------+------+---------+--------------------------+----------------------------------------------+
| | +AllNodesScan |              5 |    5 |       6 | y                        |                                              |
| |               +----------------+------+---------+--------------------------+----------------------------------------------+
| +Filter         |              3 |    3 |       0 | andres, r1, r3, x, y     | NOT(r1 == r3)                                |
| |               +----------------+------+---------+--------------------------+----------------------------------------------+
| +Expand(All)    |              3 |    4 |       5 | andres, r1, r3, x, y     | (andres)-[r3:]-(y)                           |
| |               +----------------+------+---------+--------------------------+----------------------------------------------+
| +Expand(All)    |              1 |    1 |       2 | andres, r1, x            | (andres)-[r1:]->(x)                          |
| |               +----------------+------+---------+--------------------------+----------------------------------------------+
| +Filter         |              1 |    1 |       5 | andres                   | andres.name == {  AUTOSTRING0}               |
| |               +----------------+------+---------+--------------------------+----------------------------------------------+
| +AllNodesScan   |              5 |    5 |       6 | andres                   |                                              |
+-----------------+----------------+------+---------+--------------------------+----------------------------------------------+

Total database accesses: 39