A database index is a redundant copy of information in the database for the purpose of making retrieving said data more efficient. This comes at the cost of additional storage space and slower writes, so deciding what to index and what not to index is an important and often non-trivial task.
Cypher allows the creation of indexes over a property for all nodes that have a given label. Once an index has been created, it will automatically be managed and kept up to date by the database whenever the graph is changed. Neo4j will automatically pick up and start using the index once it has been created and brought online.
Create an index
To create an index on a property for all nodes that have a label, use CREATE
INDEX
ON
. Note that the index is not immediately available, but will be created in the background.
Query
CREATE INDEX ON :Person(name)
Result
|
Try this query live create index on :`Person`(`name`); create (_0:`Person` {`name`:"Andres"}) create (_1:`Person` {`name`:"Mark"}) create (_2:`Person`) create (_3:`Person`) create (_4:`Person`) create (_5:`Person`) create (_6:`Person`) create (_7:`Person`) create (_8:`Person`) create (_9:`Person`) create (_10:`Person`) create (_11:`Person`) create (_12:`Person`) create (_13:`Person`) create (_14:`Person`) create (_15:`Person`) create (_16:`Person`) create (_17:`Person`) create (_18:`Person`) create (_19:`Person`) create (_20:`Person`) create (_21:`Person`) create (_0)-[:`KNOWS`]->(_1) ; create index on :Person(name)
Drop an index
To drop an index on all nodes that have a label and property combination, use the DROP
INDEX
clause.
Query
DROP INDEX ON :Person(name)
Result
Indexes removed: 1 |
---|
|
Try this query live create index on :`Person`(`name`); create (_0:`Person` {`name`:"Andres"}) create (_1:`Person` {`name`:"Mark"}) create (_2:`Person`) create (_3:`Person`) create (_4:`Person`) create (_5:`Person`) create (_6:`Person`) create (_7:`Person`) create (_8:`Person`) create (_9:`Person`) create (_10:`Person`) create (_11:`Person`) create (_12:`Person`) create (_13:`Person`) create (_14:`Person`) create (_15:`Person`) create (_16:`Person`) create (_17:`Person`) create (_18:`Person`) create (_19:`Person`) create (_20:`Person`) create (_21:`Person`) create (_0)-[:`KNOWS`]->(_1) ; drop index on :Person(name)
Use index
There is usually no need to specify which indexes to use in a query, Cypher will figure that out by itself. For example the query below will use the Person(name)
index, if it exists. If you want Cypher to use specific indexes, you can enforce it using hints. See Section 15.4, “Using”.
Query
MATCH (person:Person { name: 'Andres' }) RETURN person
Query Plan
+-----------------+----------------+------+---------+-----------+---------------+ | Operator | Estimated Rows | Rows | DB Hits | Variables | Other | +-----------------+----------------+------+---------+-----------+---------------+ | +ProduceResults | 1 | 1 | 0 | person | person | | | +----------------+------+---------+-----------+---------------+ | +NodeIndexSeek | 1 | 1 | 2 | person | :Person(name) | +-----------------+----------------+------+---------+-----------+---------------+ Total database accesses: 2
Use index with WHERE using equality
Indexes are also automatically used for equality comparisons of an indexed property in the WHERE clause. If you want Cypher to use specific indexes, you can enforce it using hints. See Section 15.4, “Using”.
Query
MATCH (person:Person) WHERE person.name = 'Andres' RETURN person
Query Plan
+-----------------+----------------+------+---------+-----------+---------------+ | Operator | Estimated Rows | Rows | DB Hits | Variables | Other | +-----------------+----------------+------+---------+-----------+---------------+ | +ProduceResults | 1 | 1 | 0 | person | person | | | +----------------+------+---------+-----------+---------------+ | +NodeIndexSeek | 1 | 1 | 2 | person | :Person(name) | +-----------------+----------------+------+---------+-----------+---------------+ Total database accesses: 2
Use index with WHERE using inequality
Indexes are also automatically used for inequality (range) comparisons of an indexed property in the WHERE clause. If you want Cypher to use specific indexes, you can enforce it using hints. See Section 15.4, “Using”.
Query
MATCH (person:Person) WHERE person.name > 'B' RETURN person
Query Plan
+-----------------------+----------------+------+---------+-----------+---------------------------------+ | Operator | Estimated Rows | Rows | DB Hits | Variables | Other | +-----------------------+----------------+------+---------+-----------+---------------------------------+ | +ProduceResults | 10 | 1 | 0 | person | person | | | +----------------+------+---------+-----------+---------------------------------+ | +NodeIndexSeekByRange | 10 | 1 | 2 | person | :Person(name) > { AUTOSTRING0} | +-----------------------+----------------+------+---------+-----------+---------------------------------+ Total database accesses: 2
Use index with IN
The IN predicate on person.name
in the following query will use the Person(name)
index, if it exists. If you want Cypher to use specific indexes, you can enforce it using hints. See Section 15.4, “Using”.
Query
MATCH (person:Person) WHERE person.name IN ['Andres', 'Mark'] RETURN person
Query Plan
+-----------------+----------------+------+---------+-----------+---------------+ | Operator | Estimated Rows | Rows | DB Hits | Variables | Other | +-----------------+----------------+------+---------+-----------+---------------+ | +ProduceResults | 24 | 2 | 0 | person | person | | | +----------------+------+---------+-----------+---------------+ | +NodeIndexSeek | 24 | 2 | 4 | person | :Person(name) | +-----------------+----------------+------+---------+-----------+---------------+ Total database accesses: 4
Use index with STARTS WITH
The STARTS WITH
predicate on person.name
in the following query will use the Person(name)
index, if it exists.
Query
MATCH (person:Person) WHERE person.name STARTS WITH 'And' RETURN person
Query Plan
+-----------------------+----------------+------+---------+-----------+-------------------------------------------+ | Operator | Estimated Rows | Rows | DB Hits | Variables | Other | +-----------------------+----------------+------+---------+-----------+-------------------------------------------+ | +ProduceResults | 26 | 1 | 0 | person | person | | | +----------------+------+---------+-----------+-------------------------------------------+ | +NodeIndexSeekByRange | 26 | 1 | 2 | person | :Person(name STARTS WITH { AUTOSTRING0}) | +-----------------------+----------------+------+---------+-----------+-------------------------------------------+ Total database accesses: 2
Use index when checking for the existence of a property
The has(p.name)
predicate in the following query will use the Person(name)
index, if it exists.
Query
MATCH (p:Person) WHERE exists(p.name) RETURN p
Query Plan
+-----------------+----------------+------+---------+-----------+---------------+ | Operator | Estimated Rows | Rows | DB Hits | Variables | Other | +-----------------+----------------+------+---------+-----------+---------------+ | +ProduceResults | 2 | 2 | 0 | p | p | | | +----------------+------+---------+-----------+---------------+ | +NodeIndexScan | 2 | 2 | 3 | p | :Person(name) | +-----------------+----------------+------+---------+-----------+---------------+ Total database accesses: 3