Overview
Indexing, or property indexing, is a technique used in Ultipa to accelerate the retrieval of nodes and edges with specific properties. By avoiding full graph scans, indexes enable the database to quickly locate relevant data. This is especially advantageous when working with large graphs.
Index Types
Ultipa supports single index on one property and composite index which involve multiple properties from a schema.
Showing Indexes
To retrieve node indexes in the current graph:
SHOW NODE INDEX
To retrieve edge indexes in the current graph:
SHOW EDGE INDEX
The information about indexes is organized into the _nodeIndex
or _edgeIndex
table with the following fields:
Field |
Description |
---|---|
id |
Index id. |
name |
Index name. |
properties |
The properties involved in the index. |
schema |
The schema of the properties involved in the index. |
status |
Index status, which can be DONE or CREATING . |
Creating an Index
You can create an index using the CREATE INDEX
statement. Note that each property can only have one single index. The index creation runs as a job, you may run SHOW JOB <id?>
afterward to verify the success of the creation.
System properties in Ultipa are inherently optimized for query performance and have built-in efficiencies. They do not support indexing.
<create index statement> ::=
"CREATE INDEX" <index name> "ON" < "NODE" | "EDGE" > <schema name>
"(" <property index item> [ { "," <property index item> }... ] ")"
<property index item> ::=
<property name> [ "(" <bytes> ")" ]
Details
- The
<index name>
must be unique among nodes and among edges, but a node index and an edge index may share the same name. - For a single index, specifies one
<property index item>
; for a composite index, lists multiple<property index item>
. - If a specified property is of type
string
ortext
, you can specify the maximum number of bytes [1] (count from left) to be indexed for each value. If omitted, the default indexing length is1024
bytes forstring
and2048
bytes fortext
. Learn more about how this byte-length limitation affects queries.
[1] In standard English text, most encodings (such as ASCII or UTF-8) use 1 byte per character. However, for non-English characters, the byte size may vary—for example, one Chinese character typically occupies 3 bytes.
To create single index named cBalance
for the property balance
of card
nodes:
CREATE INDEX cBalance ON NODE card (balance)
To create single index named name
for the property name
(string
type) of card
nodes, restricting the indexed byte-length as 10
:
CREATE INDEX name ON NODE card (name(10))
To create composite index named transAmountNotes
for properties amount
and notes
(text
type, restricting the indexed byte-lengt as 10
) for transfer
edges:
CREATE INDEX transAmountNotes ON EDGE transfer (amount, notes(10))
Dropping an Index
You can drop an index using the DROP NODE INDEX
or DROP EDGE INDEX
statement. Dropping an index does not affect the actual property values stored in shards.
A property with an index cannot be dropped until the index is deleted.
To drop the node index cBalance
:
DROP NODE INDEX cBalance
To drop the edge index transAmountNotes
:
DROP EDGE INDEX transAmountNotes
Using Indexes
Applicable Queries
Indexes are automatically applied when the corresponding properties are used in the following types of queries. They are not effective in other types of queries.
1. Node retrieval using a single node pattern. For example,
CREATE INDEX user_age_index ON NODE user (age)
The user_age_index
is effective in the following queries:
MATCH (n:user {age: 45}) RETURN n
MATCH (n) WHERE n.age > 45 RETURN n
In the second query, the node label is not specified, so user_age_index
is only partially used during the search for user
nodes.
2. Edge retrieval using a one-step path pattern. For example,
CREATE INDEX links_weight_index ON EDGE links (weight)
The links_weight_index
is effective in the following query:
MATCH ()-[e:links WHERE e.weight = 2]->() RETURN e
The edge direction can be left (<-[]-
), right (-[]->
), or any (-[]-
).
The following query does not use links_weight_index
because it retrieves paths, not edges:
MATCH p = ()-[e:links WHERE e.weight = 2]->() RETURN p
3. Start node filtering in path patterns.
The above user_age_index
is effective in the following query:
MATCH p = (n:user WHERE n.age > 45)-[]-()-[]-() RETURN p
It does not apply to the following query:
MATCH p = ()-[]-(n:user WHERE n.age > 45) RETURN p
Leftmost Prefix Rule
The order of properties in a composite index matters — queries that match the leftmost properties of the index (i.e., the first property or the first few properties in the defined order) will benefit from the index.
For example:
CREATE INDEX name_age ON NODE user (name(10),age)
MATCH (u:user WHERE u.name = "Kavi" AND u.age > 20)
uses the index.MATCH (u:user WHERE u.name = "Kavi")
uses the index.MATCH (u:user WHERE u.age > 20)
doesn't use the index.MATCH (u:user WHERE u.name = "Kavi" AND u.age > 20 AND u.grade = 7)
uses the index, meanwhile it contains the filtering for thegrade
property which lacks an index.
String Byte-Length Limitation
When using indexes with string
or text
properties, ensure the byte-length of the string used in the filter does not exceed the defined limit when creating the index.
For example, an index Username
is created for the name
property of the user
nodes with a 8-byte limitation:
CREATE INDEX Username ON NODE user (name(8))
The query below won't utilize the Username
index as the specified string Aventurine
exceeds the 8-byte limit:
MATCH (n:user {name: "Aventurine"})
RETURN n