Graph Service
Graph Service is a built-in Property Graph capability in AnalyticDB for MySQL for ADB version 328 and later. This topic describes how to enable Graph Service, build data models, read and write data, and perform common queries.
Enable and use Graph Service
Graph Service is suitable for large language model (LLM) and Agent scenarios. It models business entities, knowledge, tasks, tools, and events as a graph to provide LLMs with traceable relational context, single-hop and multi-hop relationship queries, and path exploration capabilities.
To use Graph Service, submit a ticket to enable it. After enabling, you can run Gremlin statements directly on the AnalyticDB for MySQL SQL execution page:
-
Use
graph.schema()to define data models and indexes. -
Use
gto write, query, update, and delete data. -
View execution results or error messages directly on the page.
You do not need to deploy a separate graph database or handle authentication, instance identification, or request forwarding for Graph Service.
Typical AI/Agent use cases
-
Knowledge association: Query relationships between entities, products, documents, and rules.
-
Agent paths and dependencies: Query dependencies and impact ranges between tasks, tools, datasets, and owners.
-
Risk and tracing: Starting from a customer, device, or event, find related relationships and propagation paths.
-
Joint analysis: Use graph traversal to narrow down associated objects, then combine ADB detail data for filtering and analysis.
Basic concepts
A graph consists of three types of objects:
|
Object |
Description |
Example |
|
Vertex |
A vertex that represents a business entity |
User, device, product |
|
Edge |
A directed relationship between entities |
Follow, purchase, invoke |
|
Property |
An attribute on a vertex or edge |
Name, age, time, weight |
Build a schema
Before writing business data, you must create a schema:
graph.schema().propertyKey("name").asText().ifNotExist().create()
graph.schema().propertyKey("age").asInt().ifNotExist().create()
graph.schema().vertexLabel("person")
.properties("name", "age")
.nullableKeys("age")
.useAutomaticId()
.ifNotExist().create()
graph.schema().edgeLabel("knows")
.sourceLabel("person")
.targetLabel("person")
.properties("since")
.ifNotExist().create()
Create indexes for querying:
graph.schema().indexLabel("personByName")
.onV("person").by("name").secondary()
.ifNotExist().create()
graph.schema().indexLabel("personByAge")
.onV("person").by("age").range()
.ifNotExist().create()
Write data
After creating vertices, save the returned vertex IDs for subsequent queries and edge creation:
# Return alice vertex id: aliceVertexId
g.addV("person").property("name", "alice").property("age", 25).next()
# Return bob vertex id: bobVertexId
g.addV("person").property("name", "bob").property("age", 30).next()
# Return caz vertex id: cazVertexId
g.addV("person").property("name", "caz").property("age", 30).next()
# Create edges: alice -> bob -> caz
g.addE("knows").from(__.V(aliceVertexId)).to(__.V(bobVertexId)).property("since", 2024).iterate()
g.addE("knows").from(__.V(bobVertexId)).to(__.V(cazVertexId)).property("since", 2024).iterate()
Common queries
g.V(vertexId).valueMap(true).next()
g.V().hasLabel("person").has("name", "alice").limit(20).valueMap(true).toList()
g.V(vertexId).out("knows").limit(20).valueMap(true).toList()
For online queries, start from IDs, indexed conditions, or known vertices, and always set limit. Avoid placing full-graph count(), deep pagination, and global order().by(...).limit(...) in high-frequency online requests.
Query schema definitions:
# Query a single schema definition
graph.schema().getPropertyKey("name")
graph.schema().getVertexLabel("person")
graph.schema().getEdgeLabel("knows")
graph.schema().getIndexLabel("personByAge")
# Query all schema definitions
graph.schema().getPropertyKeys().toList()
graph.schema().getVertexLabels().toList()
graph.schema().getEdgeLabels().toList()
graph.schema().getIndexLabels().toList()
Delete data and schema
The recommended deletion order is: IndexLabel, EdgeLabel, VertexLabel, PropertyKey.
# Update vertex property
g.V(vertexId).property("age", 26).iterate()
# Delete edges
g.E().hasLabel("knows").drop()
# Delete vertex
g.V(vertexId).outE("knows").drop().iterate()
g.V(vertexId).drop().iterate()
# Delete all data
g.E().drop()
g.V().drop()
Delete schema:
# The async cleanup task returns a taskId. You can use this ID to check the task progress.
graph.schema().edgeLabel("knows").remove()
graph.schema().vertexLabel("person").remove()
graph.schema().propertyKey("name").remove()
Check async cleanup task status:
graph.task.{taskId}
Limits and troubleshooting
-
Data, schemas, and tasks are isolated across ADB instances.
-
The standard query language is Gremlin. Cypher, SQL, Bolt, and APOC are not supported.
-
For syntax or schema errors, fix the statement instead of retrying directly.
-
When throttled, reduce concurrency and retry with backoff.
FAQ
Do I need to add cluster or isolation fields?
No. ADB automatically performs cluster-level data isolation.
Can different AnalyticDB for MySQL clusters use the same schema name?
Yes. Data is not affected.
Why can I not query by a field after creating a unique constraint?
unique is for write uniqueness. To query, create a secondary index.
Can I query data immediately after writing?
Yes.