Skip to content
Open
Show file tree
Hide file tree
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
215 changes: 215 additions & 0 deletions src/content/doc-surrealql/statements/explain.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
---
sidebar_position: 9
sidebar_label: EXPLAIN
title: EXPLAIN statement | SurrealQL
description: The REBUILD statement is used to rebuild resources.
---

import Since from '@components/shared/Since.astro'
import SurrealistMini from "@components/SurrealistMini.astro"
import RailroadDiagram from "@components/RailroadDiagram.astro"
import Tabs from "@components/Tabs/Tabs.astro"
import TabItem from "@components/Tabs/TabItem.astro"

# `EXPLAIN` statement

<Since v="v3.0.0" />

> [!NOTE]
> The output for the `EXPLAIN` statement is for informational purposes and subject to change. Be sure not to develop tools around it that rely on a single predictible output.

The `EXPLAIN` statement is used to display the query planner for a statement.

### Statement syntax

<Tabs syncKey="rebuild-statement">
<TabItem label="SurrealQL Syntax">

```syntax title="SurrealQL Syntax"
EXPLAIN [ ANALYZE ] [ FORMAT TEXT | JSON ] @statement
```

</TabItem>
<TabItem label="Railroad Diagram">

export const explainAst = {
type: "Diagram",
padding: [10, 20, 10, 20],
children: [
{ type: "Sequence", children: [
{ type: "Terminal", text: "EXPLAIN" },
{ type: "Optional", child: { type: "Terminal", text: "ANALYZE" } },
{ type: "Optional", child: {
type: "Sequence", children: [
{ type: "Terminal", text: "FORMAT" },
{ type: "Choice", index: 0, children: [
{ type: "Terminal", text: "TEXT" },
{ type: "Terminal", text: "JSON" }
]}
]
}},
{ type: "NonTerminal", text: "@statement" }
]}
]
};


<RailroadDiagram ast={explainAst} className="my-6" />

</TabItem>
</Tabs>

## Example usage

An `EXPLAIN` statement is one that can be appended to another statement that does not modify database resources, i.e. a `SELECT` statement or another statement that returns a value.

The two main decisions to make when using an `EXPLAIN` statement are:

* Use default text format or add `FORMAT JSON` to output the format in JSON?
* Add the `ANALYZE` clause after `EXPLAIN`

The following example shows the four possible types of output when followed by a simple string.

```surql
EXPLAIN "yourself!";
EXPLAIN ANALYZE "yourself!";
EXPLAIN FORMAT JSON "yourself!";
EXPLAIN ANALYZE FORMAT JSON "yourself!";
```

As the output shows, the `ANALYZE` clause adds information on the metrics and total rows.

```surql title="Output"
-------- Query --------

"Expr [ctx: Rt] [expr: 'yourself!']\n"

-------- Query --------

"Expr [ctx: Rt] [expr: 'yourself!'] {rows: 0, batches: 0, elapsed: 0ns}\n\nTotal rows: 1"

-------- Query --------

{
attributes: {
expr: "'yourself!'"
},
context: 'Rt',
operator: 'Expr'
}

-------- Query --------

{
attributes: {
expr: "'yourself!'"
},
context: 'Rt',
metrics: {
elapsed_ns: 0,
output_batches: 0,
output_rows: 0
},
operator: 'Expr',
total_rows: 1
}
```

### Context

The `context` field in an `EXPLAIN` statement refers to the minimum context level for an operation: `Rt` (root), `Ns` (namespace), or `Db` (database) level.

### Operator types

The `operator` field in the output of an `EXPLAIN` statement is the most relevant area to take note of. Here is a list of many of the operator types you will see in the statement output.

```text
Aggregate
Compute
CountScan
Explain
ExplainAnalyze
Expr
Fetch
Filter
Foreach
FullTextScan
GraphEdgeScan
IfElse
IndexCountScan
IndexScan
Let
Limit
ProjectValue
Project
SelectProject
ReferenceScan
Return
Scan
Sequence
Sleep
SourceExpr
Split
Union
UnwrapExactlyOne
InfoDatabase
InfoIndex
InfoNamespace
InfoRoot
InfoTable
InfoUser
ExternalSort
Sort
SortByKey
RandomShuffle
SortTopK
SortTopKByKey
```

This allows you to get an insight into exactly what sort of work is being performed by the database when a query is executed.

For example, take the following simple example in which one `person` record has a single friend. The final two queries return the same result, but one is a `SELECT...FROM ONLY` query while the other is a direct destructuring of the link from its record id.

```surql
CREATE person:one, person:two;
RELATE person:one->friend->person:two;

EXPLAIN SELECT ->friend->person AS friends FROM ONLY person:one;
EXPLAIN person:one.{ friends: ->friend->person };
```

Not only is the second query faster, but we can see why: the first query is doing more work: three `[ctx: Db]` operations instead of one. The first query begins with a `Scan`, includes projections (`Project`, namely the field name(s) for a `SELECT`), followed by an `UnwrapExactlyOne` (the `FROM ONLY` clause).

```surql title="Output"
-------- Query 1 (147us) --------

'UnwrapExactlyOne [ctx: Db]
└────> Project [ctx: Db]
└────> Scan [ctx: Db] [source: person:one]'

-------- Query 2 (52us) --------

'Expr [ctx: Db] [expr: (person:one).{ friends: ->friend->person }]'
```

Here is an example of output for a query of a complexity more similar to those seen in production applications.

```surql
EXPLAIN ANALYZE SELECT
id as commentId,
in.id as id,
in.creationDate as creationDate
FROM is_comment_of
WHERE out = media_text_test:0 AND in.creationDate < d'2026-01-09T00:00:00.000Z'
ORDER BY in.creationDate DESC
LIMIT 2;
```

```surql title="Output"
"Project [ctx: Db] {rows: 0, batches: 0, elapsed: 2.84ms}
└────> Limit [ctx: Db] [limit: 2] {rows: 0, batches: 0, elapsed: 2.81ms}
└────> SortTopKByKey [ctx: Db] [sort_keys: in.creationDate DESC, limit: 2] {rows: 0, batches: 0, elapsed: 2.78ms}
└────> Scan [ctx: Db] [source: is_comment_of, predicate: out = media_text_test:0 AND in.creationDate < d'2026-01-09T00:00:00Z'] {rows: 0, batches: 0, elapsed: 2.69ms}

Total rows: 0"
```
2 changes: 1 addition & 1 deletion src/content/doc-surrealql/statements/for.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 9
sidebar_position: 10
sidebar_label: FOR
title: FOR statement | SurrealQL
description: The FOR statement creates a loop that iterates over the values of an array.
Expand Down
2 changes: 1 addition & 1 deletion src/content/doc-surrealql/statements/ifelse.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 10
sidebar_position: 11
sidebar_label: IF ELSE
title: IF ELSE statement | SurrealQL
description: The IF ELSE statement can be used as a main statement, or within a parent statement, to return a value depending on whether a condition, or a series of conditions match.
Expand Down
2 changes: 1 addition & 1 deletion src/content/doc-surrealql/statements/info.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 11
sidebar_position: 12
sidebar_label: INFO
title: INFO statement | SurrealQL
description: The INFO command outputs information about the setup of the SurrealDB system.
Expand Down
2 changes: 1 addition & 1 deletion src/content/doc-surrealql/statements/insert.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 12
sidebar_position: 13
sidebar_label: INSERT
title: INSERT statement | SurrealQL
description: The INSERT statement can be used to insert or update data into the database, using the same statement syntax as the traditional SQL Insert statement.
Expand Down
2 changes: 1 addition & 1 deletion src/content/doc-surrealql/statements/kill.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 13
sidebar_position: 14
sidebar_label: KILL
title: KILL statement | SurrealQL
description: The KILL statement is used to terminate a running live query.
Expand Down
2 changes: 1 addition & 1 deletion src/content/doc-surrealql/statements/let.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 14
sidebar_position: 15
sidebar_label: LET
title: LET statement | SurrealQL
description: The LET statement sets and stores a value which can then be used in a subsequent query.
Expand Down
2 changes: 1 addition & 1 deletion src/content/doc-surrealql/statements/live.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 15
sidebar_position: 16
sidebar_label: LIVE
title: LIVE SELECT statement | SurrealQL
description: The LIVE SELECT statement can be used to initiate a real-time selection from a table, including the option to apply filters.
Expand Down
2 changes: 1 addition & 1 deletion src/content/doc-surrealql/statements/rebuild.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 16
sidebar_position: 17
sidebar_label: REBUILD
title: REBUILD statement | SurrealQL
description: The REBUILD statement is used to rebuild resources.
Expand Down
2 changes: 1 addition & 1 deletion src/content/doc-surrealql/statements/relate.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 17
sidebar_position: 18
sidebar_label: RELATE
title: RELATE statement | SurrealQL
description: The RELATE statement can be used to generate graph edges between two records in the database.
Expand Down
2 changes: 1 addition & 1 deletion src/content/doc-surrealql/statements/remove.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 18
sidebar_position: 19
sidebar_label: REMOVE
title: REMOVE statement | SurrealQL
description: The REMOVE statement is used to remove resources such as databases, tables, indexes, events and more.
Expand Down
2 changes: 1 addition & 1 deletion src/content/doc-surrealql/statements/return.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 19
sidebar_position: 20
sidebar_label: RETURN
title: RETURN statement | SurrealQL
description: The RETURN statement can be used to return an implicit value or the result of a query, and to set the return value for a transaction, block or function.
Expand Down
2 changes: 1 addition & 1 deletion src/content/doc-surrealql/statements/select.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 20
sidebar_position: 21
sidebar_label: SELECT
title: SELECT statement | SurrealQL
description: The SELECT statement can be used for selecting and querying data in a database.
Expand Down
2 changes: 1 addition & 1 deletion src/content/doc-surrealql/statements/show.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 21
sidebar_position: 22
sidebar_label: SHOW
title: SHOW statement | SurrealQL
description: The SHOW statement can be used to replay changes made to a table.
Expand Down
2 changes: 1 addition & 1 deletion src/content/doc-surrealql/statements/sleep.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 22
sidebar_position: 23
sidebar_label: SLEEP
title: SLEEP statement | SurrealQL
description: The SLEEP statement is used to introduce a delay or pause in the execution of a query or a batch of queries for a specific amount of time.
Expand Down
2 changes: 1 addition & 1 deletion src/content/doc-surrealql/statements/throw.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 23
sidebar_position: 24
sidebar_label: THROW
title: THROW statement | SurrealQL
description: The THROW statement can be used to stop execution of a query and return information on the underlying problem
Expand Down
2 changes: 1 addition & 1 deletion src/content/doc-surrealql/statements/update.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 24
sidebar_position: 25
sidebar_label: UPDATE
title: UPDATE statement | SurrealQL
description: The UPDATE statement can be used to update records in the database. If they already exist, they will be updated. If they do not exist, no records will be updated.
Expand Down
2 changes: 1 addition & 1 deletion src/content/doc-surrealql/statements/upsert.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 25
sidebar_position: 26
sidebar_label: UPSERT
title: UPSERT statement | SurrealQL
description: The UPSERT statement can be used to insert records or modify records that already exist
Expand Down
2 changes: 1 addition & 1 deletion src/content/doc-surrealql/statements/use.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 26
sidebar_position: 27
sidebar_label: USE
title: USE statement | SurrealQL
description: The USE statement specifies a namespace and / or a database to use for the subsequent SurrealQL statements when switching between namespaces and databases.
Expand Down