Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions pages/fundamentals/indexes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ label-property combination using the `CREATE INDEX ON` syntax or `CREATE EDGE IN

### Label index

<Callout type="info">

This index supports non-blocking creation: reads continue without interruption,
while writes are briefly paused. For more information, see the [concurrent index
creation](#concurrent-index-creation).

</Callout>

To optimize queries that fetch nodes by label, you need to create a label index:

```cypher
Expand All @@ -103,6 +111,14 @@ DROP INDEX ON :Label;

### Label-property index

<Callout type="info">

This index supports non-blocking creation: reads continue without interruption,
while writes are briefly paused. For more information, see the [concurrent index
creation](#concurrent-index-creation).

</Callout>

To optimize queries that fetch nodes with a certain label and property
combination, you need to create a label-property index. For the best
performance, create an index on properties containing unique integer values.
Expand Down Expand Up @@ -208,6 +224,14 @@ DROP INDEX ON :Label(property);

### Label-property composite index

<Callout type="info">

This index supports non-blocking creation: reads continue without interruption,
while writes are briefly paused. For more information, see the [concurrent index
creation](#concurrent-index-creation).

</Callout>

An index on a label and two or more properties is called a **composite index**.
Composite indices optimize queries where multiple properties are commonly used
together in filtering clauses, or when uniqueness exists in a combination of
Expand Down Expand Up @@ -355,6 +379,14 @@ DROP INDEX ON :Label(property1, property2);

### Edge-type index

<Callout type="info">

This index supports non-blocking creation: reads continue without interruption,
while writes are briefly paused. For more information, see the [concurrent index
creation](#concurrent-index-creation).

</Callout>

To optimize queries that fetch only the edges by specific edge-types, you need
to create an edge-type index. Creating an edge-type index requires the
`--storage-properties-on-edges` flag to be set to true.
Expand Down Expand Up @@ -385,6 +417,14 @@ DROP EDGE INDEX ON :EDGE_TYPE;

### Edge-type property index

<Callout type="info">

This index supports non-blocking creation: reads continue without interruption,
while writes are briefly paused. For more information, see the [concurrent index
creation](#concurrent-index-creation).

</Callout>

To optimize queries that fetch only the edges by specific edge types and
properties, you need to create an edge-type property index. Creating an
edge-type property index requires the `--storage-properties-on-edges` flag to be
Expand Down Expand Up @@ -415,6 +455,14 @@ DROP EDGE INDEX ON :EDGE_TYPE(property_name);

### Global edge property index

<Callout type="info">

This index supports non-blocking creation: reads continue without interruption,
while writes are briefly paused. For more information, see the [concurrent index
creation](#concurrent-index-creation).

</Callout>

Since edges can have only one edge type, Memgraph provides a way to index all the edges that contain
a certain property via the global edge index. The syntax to index all the edges that have a certain property is
the following:
Expand Down Expand Up @@ -821,3 +869,35 @@ based on the type, and secondly for values within that type.
In the case of composite indices, the list is lexicographically ordered, which
means that the pair $(a_1, a_2)$ is ordered before $(b_1, b_2)$ if either $a_1 <
b_1$, or $a_1 = b_1$ and $a_2 < b_2$.

### Concurrent index creation

Memgraph supports **(almost) fully concurrent index creation** for all
skiplist-based indices, including label, label-property, composite, edge-type,
edge-type property, and global edge property, with minimal impact on
performance.

The three-phase implementation begins with a brief **registration phase** that
requires `READ ONLY` access. This ensures that all pending write transactions
complete before the index creation begins. During this phase, the database waits
for ongoing writes to finish (typically milliseconds) while blocking new write
transactions. Read queries are not affected by this.

Once registered:
- Read queries continue uninterrupted throughout index creation
- Write operations can proceed concurrently after registration
- Existing data is indexed in the background

If you encounter write transaction failures during registration, you can
increase the wait time using the `--storage-access-timeout-sec` flag, which
extends how long write queries will retry before failing.

The system maintains **full MVCC consistency** throughout the process, ensuring
transactional integrity. Long-running index operations can be safely cancelled
if needed. Currently, some features like replication synchronization and TTL
indices still use blocking mode during operations, though these limitations will
be addressed in future releases.

For complete technical details about the implementation, consistency guarantees,
and current limitations, please refer to the [Concurrent Index Creation
ADR](https://github.com/memgraph/memgraph/blob/master/ADRs/004_concurrent_index_creation.md).