A new universe for your graph data.Meet Galactus DB
GALACTUS DB WIKIDeployment · Queries · Operations

Property, range and composite indexes

Wiki / Indexes and constraints

On this page

Property indexes

A property index on (label, property) turns MATCH (n:Label {prop: v}) and WHERE n.prop = v from an O(|nodes|) scan into an O(1)/O(log n) lookup.

CREATE INDEX ON :Person(email);     // declare (backfills existing data)
SHOW INDEXES;                       // property, composite and element indexes

The planner uses an index automatically when a pattern/predicate allows it. Confirm with EXPLAIN:

EXPLAIN MATCH (p:Person {email: $e}) RETURN p;
// Match: NodeIndexSeek(:Person .email)      <- index is used

Notes:

  • Creating an index backfills existing matching nodes — every node that carries the label at that moment, under each of its labels — and every later write keeps it current. Only nodes are indexed: there are no relationship property indexes, and an unlabelled node is never indexed. Re-declaring an existing index is accepted but re-scans the label.
  • A built-in label/token index is always on (not declared), making MATCH (n:Label) cost O(label population) rather than O(all nodes); the planner anchors a multi-label pattern on its rarest label.
  • The plain CREATE INDEX index is hash/equality only. For range queries, declare a range index (Property, range and composite indexes). Composite non-unique indexes are supported (see below); composite uniqueness uses node keys, Constraints and shared uniqueness.

Range (ordered) indexes

A range index is ordered, so it accelerates </<=/>/>= predicates (and equality) — the planner uses it when a clause WHERE ranges over the indexed property.

CREATE RANGE INDEX FOR (p:Person) ON (p.age);   // 5.x form (a name may precede FOR)
SHOW INDEXES;                                    // the `type` column shows RANGE vs BTREE
EXPLAIN MATCH (p:Person) WHERE p.age >= 18 AND p.age < 65 RETURN p;
// Match: NodeIndexSeekByRange(:Person .age)     <- range index is used

STARTS WITH is a range in disguise, and plans the same seek: the prefix desugars to >= prefix AND < successor(prefix) internally, for a literal or a parameter prefix alike.

CREATE RANGE INDEX FOR (p:Person) ON (p.name);
EXPLAIN MATCH (p:Person) WHERE p.name STARTS WITH 'Al' RETURN p;
// Match: NodeIndexSeekByRange(:Person .name)    <- prefix seek

Composite (multi-property) indexes

Both kinds take a property list, giving a composite index over several properties of a label:

CREATE INDEX FOR (p:Person) ON (p.first, p.last);        // composite hash
CREATE RANGE INDEX FOR (e:Event) ON (e.category, e.day); // composite range
  • A composite index covers a node only when it carries the label and every indexed property — a node missing one is simply not indexed.

  • The planner uses a composite hash index when every property is bound by equality (WHERE p.first = $f AND p.last = $l, or the inline form (:Person {first: $f, last: $l})), and prefers it over a single-property index when it binds more properties:

    EXPLAIN MATCH (p:Person) WHERE p.first = 'Ada' AND p.last = 'Lovelace' RETURN p;
    // Match: NodeIndexSeek(:Person (first, last))
    
  • A composite range index serves a leading-prefix equality plus an optional range on the next property (WHERE e.category = 'a' AND e.day >= 5).

  • SHOW INDEXES lists a composite index with its properties joined in the property column. Composite uniqueness is provided separately by node-key constraints (Constraints and shared uniqueness.

Removing indexes

After the examples, remove indexes with DROP INDEX ON :Person(email), DROP RANGE INDEX FOR (p:Person) ON (p.age) or DROP INDEX FOR (p:Person) ON (p.first, p.last). A constraint-backed index cannot be dropped while its constraint exists.

EXPLAIN and PROFILE · Resident and hybrid storage · Schema and maintenance procedures

Planning a deployment? Review compatibility and licence setup for your instance.