# EXPLAIN

The `EXPLAIN` clause is used to explain the plan used for a query.

The `EXPLAIN` clause is used to explain the plan used for a query. It is particularly useful when you want to understand how a query is executed and how it is optimised by the database.

When `EXPLAIN` is used, the statement returns an explanation, essentially revealing the execution plan to provide transparency and understanding of the query performance.

## Syntax

```syntax title="Clause Syntax"
@query EXPLAIN [FULL]
```

Using the `EXPLAIN` clause in addition to the `FULL` keyword is expeciallly useful when you want to understand the performance of a query and can provide more details when debugging.

## Examples

For example, consider the performance of the following query when the field `email` is not indexed. We can see that the execution plan will iterate over the whole table.

```surql title="Index not used"
CREATE person:tobie SET
	name = "Tobie",
	address = "1 Bagshot Row",
	email = "tobie@surrealdb.com";

SELECT * FROM person WHERE email='tobie@surrealdb.com' EXPLAIN;
SELECT * FROM person WHERE email='tobie@surrealdb.com' EXPLAIN FULL;
```

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

{
	attributes: {
		projections: '*'
	},
	children: [
		{
			attributes: {
				direction: 'Forward',
				predicate: "email = 'tobie@surrealdb.com'",
				table: 'person'
			},
			context: 'Db',
			operator: 'TableScan'
		}
	],
	context: 'Db',
	operator: 'SelectProject'
}

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

{
	attributes: {
		projections: '*'
	},
	children: [
		{
			attributes: {
				direction: 'Forward',
				predicate: "email = 'tobie@surrealdb.com'",
				table: 'person'
			},
			context: 'Db',
			metrics: {
				elapsed_ns: 66543,
				output_batches: 1,
				output_rows: 1
			},
			operator: 'TableScan'
		}
	],
	context: 'Db',
	metrics: {
		elapsed_ns: 8251,
		output_batches: 1,
		output_rows: 1
	},
	operator: 'SelectProject',
	total_rows: 1
}
```

On the other hand, here is the result when the field `email` is indexed. We can see that the execution plan will use the index to retrieve the record.

```surql title="Index used"
DEFINE INDEX fast_email ON TABLE person FIELDS email;

CREATE person:tobie SET
	name = "Tobie",
	address = "1 Bagshot Row",
	email = "tobie@surrealdb.com";

SELECT * FROM person WHERE email='tobie@surrealdb.com' EXPLAIN;
SELECT * FROM person WHERE email='tobie@surrealdb.com' EXPLAIN FULL;
```

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

{
	attributes: {
		projections: '*'
	},
	children: [
		{
			attributes: {
				access: "= 'tobie@surrealdb.com'",
				direction: 'Forward',
				index: 'fast_email'
			},
			context: 'Db',
			operator: 'IndexScan'
		}
	],
	context: 'Db',
	operator: 'SelectProject'
}

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

{
	attributes: {
		projections: '*'
	},
	children: [
		{
			attributes: {
				access: "= 'tobie@surrealdb.com'",
				direction: 'Forward',
				index: 'fast_email'
			},
			context: 'Db',
			metrics: {
				elapsed_ns: 48624,
				output_batches: 1,
				output_rows: 1
			},
			operator: 'IndexScan'
		}
	],
	context: 'Db',
	metrics: {
		elapsed_ns: 4999,
		output_batches: 1,
		output_rows: 1
	},
	operator: 'SelectProject',
	total_rows: 1
}
```

### K-nearest neighbours (KNN) searches

_(since v3.1.5)_

When a [KNN search](/docs/reference/query-language/language-primitives/operators.md#knn) over an indexed vector field is combined with an additional non-KNN condition, that condition is pushed *into* the index search so that non-matching candidates are rejected during the search rather than afterwards. The plan shows this as a `predicate` attribute on the `KnnScan` operator. To display the query plan, add the `EXPLAIN` clause to the end of a query as shown in the example below.

```surql title="Filtered KNN"
DEFINE INDEX idx_pt ON pts FIELDS point HNSW DIMENSION 4;
INSERT INTO pts [
	{ point: [1, 2, 3, 4], flag: true },
	{ point: [4, 3, 2, 1], flag: false },
	{ point: [3, 3, 3, 3], flag: true }
];

SELECT id, flag, vector::distance::knn() AS distance FROM pts
	WHERE flag = true AND point <|2,40|> [2, 3, 4, 5]
	ORDER BY distance EXPLAIN;
```

```surql title="Output"
{
	attributes: {
		projections: 'id, flag, distance'
	},
	children: [
		{
			attributes: {
				sort_keys: 'distance ASC'
			},
			children: [
				{
					attributes: {
						fields: 'distance = vector::distance::knn(...)'
					},
					children: [
						{
							attributes: {
								predicate: 'flag = true'
							},
							children: [
								{
									attributes: {
										dimension: '4',
										ef: '40',
										index: 'idx_pt',
										k: '2',
										predicate: 'flag = true'
									},
									context: 'Db',
									operator: 'KnnScan'
								}
							],
							context: 'Db',
							expressions: [
								{
									role: 'predicate',
									sql: 'flag = true'
								}
							],
							operator: 'Filter'
						}
					],
					context: 'Db',
					expressions: [
						{
							role: 'distance',
							sql: 'vector::distance::knn(...)'
						}
					],
					operator: 'Compute'
				}
			],
			context: 'Db',
			operator: 'SortByKey'
		}
	],
	context: 'Db',
	operator: 'SelectProject'
}
```

The innermost `KnnScan` operator carries the `predicate: 'flag = true'` attribute - the condition that is evaluated inside the index search. The same condition also appears on the `Filter` operator above it. Adding `EXPLAIN FULL` includes per-operator `metrics`. The query plan is identical for a DISKANN index. For a guided walkthrough, see [Filtering through vector search](/docs/learn/data-models/vector-search/similarity-search.md#how-the-filter-is-applied).
