Indexes
Indexes allow queries to quickly locate data without having to look through each document in a collection.
By default, every collection has an index on the _docID property and on @primary relationship fields.
The @index directive allows you to set up further indexes on selected properties.
Syntax
@index(
name: String,
unique: Boolean,
direction: ORDERING,
includes: [{ field: String, direction: ORDERING }]
)
name– Index name.
Default: concatenation of collection name, field names, direction.unique– Enforce uniqueness constraint (i.e. no two documents can have the same value for the given fields).
Default:false.direction– Order direction. This affects the default sorting of results when querying documents.
Valid values:ASCorDESC.
Default:ASC.includes– List of fields the index is created on (not required when the directive is used in a field definition).
Index single fields
To create an index for a specific field, use the @index directive on the field when creating the collection.
type Book {
title: String @index
}
type Book {
title: String @index(name: "book_title")
plot: String @index(name: "book_plot")
}
type Book {
title: String
author: Person @primary @index
}
type Person {
name: String
books: [Book]
}
Unique indexes
An indexed unique field ensures that no two documents have the same value for one field. Null values are still allowed though.
type Book {
title: String @index(unique: true)
}
Unique indexes are used under the hood to enforce one-to-one relationships. The index must not be dropped, or the 1:1 nature of the relationship will not be fulfilled anymore.
Indexes multiple fields (composite)
To create an index on the combination of multiple fields (composite index), use the @index directive at the collection level.
type Book @index(includes: [{ field: "genre" }, { field: "author" }]) {
genre: String
author: String
}
The order of fields in includes defines the structure of the index. An index defined on fields genre and author gives no performance benefit to queries filtering only on author. Think of a composite index storing references to documents in a hierarchical structure defined by its order:
Fiction/David Foster Wallace/docID1
Fiction/David Foster Wallace/docID2
Fiction/George Orwell/docID3
Fiction/George Orwell/docID4
Physics/Richard Feynman/docID5
...
Although there is a partial benefit to queries filtering only on genre, there is no benefit if a query skips fields.
JSON fields
If a JSON field is indexed, queries can traverse the JSON structure and filter by its inner properties. See Filter documents -> JSON fields.
Scalar types (ex. integers) are normalized to DefraDB types (ex. int64).
Performance considerations
More indexes is not better. The right indexes is better.
An index can improve read performance, but it will decrease write performance, because every document update/create must also update the relevant indexes.
- Create indexes based on your query patterns. If you are tempted to index every field, remember that there's no free lunch and that the overhead (in storage and write speed) likely outweighs the benefit.
- Use unique indexes only when necessary. Because they require extra validation, their performance impact is more significant.