Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DOC-723 | Query plan caching #641

Merged
merged 13 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from 3 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
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ Apple silicon like M1).

Run the `docker compose` services using the `docker-compose.pain-build.yml` file.

```shell
```sh
docs-hugo/toolchain/docker/amd64> docker compose -f docker-compose.plain-build.yml up --abort-on-container-exit
```

Expand All @@ -179,7 +179,7 @@ To make the documentation tooling not start a live server in watch mode but
rather create a static build and exit, set the environment variable `ENV` to
any value other than `local` before calling `docker compose ...`:

```shell
```sh
export ENV=static # Bash
set -xg ENV static # Fish
$Env:ENV='static' # PowerShell
Expand Down Expand Up @@ -215,7 +215,7 @@ The generators entry is a space-separated string.
If `metrics` or `error-codes` is in the `generators` string, the following
environment variable has to be exported:

```shell
```sh
export ARANGODB_SRC_{VERSION}=path/to/arangodb/source
```

Expand Down Expand Up @@ -246,7 +246,7 @@ Apple silicon like M1).

Run the `docker compose` services without specifying a file:

```shell
```sh
docs-hugo/toolchain/docker/arm64> docker compose up --abort-on-container-exit
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,12 @@ see [arangodb.com/community-server/](https://www.arangodb.com/community-server/)
collection scans. Inlining of certain subqueries to improve execution time.
<!-- TODO, move to Querying? -->

{{% comment %}} Experimental feature in v3.12.4
- [**Query plan caching**](../../aql/execution-and-performance/caching-query-plans.md)
Reduce the total time for processing queries by avoiding to parse, plan, and
optimize the same queries over and over again with an AQL execution plan cache.
Simran-B marked this conversation as resolved.
Show resolved Hide resolved
{{% /comment %}}

- [**Parallel gather**](../../release-notes/version-3.11/whats-new-in-3-11.md#parallel-gather):
Fast, memory-efficient processing of cluster queries by combining
results in parallel.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ aliases:
Speed up data transfers and reduce traffic with transparent compression of
requests and responses between ArangoDB servers and client tools.

{{% comment %}} Experimental feature in v3.12.4
- [**Query plan caching**](../../aql/execution-and-performance/caching-query-plans.md)
Reduce the total time for processing queries by avoiding to parse, plan, and
optimize the same queries over and over again with an AQL execution plan cache.
Simran-B marked this conversation as resolved.
Show resolved Hide resolved
{{% /comment %}}

**Enterprise Edition**

- [**ArangoSearch WAND optimization**](../../index-and-search/arangosearch/performance.md#wand-optimization):
Expand Down
190 changes: 190 additions & 0 deletions site/content/3.12/aql/execution-and-performance/caching-query-plans.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
---
title: The AQL query execution plan cache
menuTitle: Caching query plans
weight: 29
description: >-
AQL provides an optional cache for query plans to skip query planning and
optimization when running the same queries repeatedly
Simran-B marked this conversation as resolved.
Show resolved Hide resolved
---
Query plan caching can reduce the total time for processing queries by avoiding
to parse, plan, and optimize queries over and over again that effectively have
the same execution plan with at most some changes to bind parameter values.
It is especially useful for particular queries where a lot of time is spent on
the query planning and optimization passes in proportion to the actual execution.

## Use plan caching for queries

Query plans are not cached by default. You need to enable the query option for
plan caching on a per-query basis to utilize cached plans as well as to add
plans to the cache. Otherwise, the plan cache is bypassed.

{{< tabs "interfaces" >}}

{{< tab "Web interface" >}}
1. Click **Queries** in the main navigation.
2. Enter an AQL query and specify the values for bind variables if necessary.
3. Switch to the **Options** tab to access the query options.
4. Expand the **Advanced** panel.
5. Enable the **Use Plan Cache** option.
{{< /tab >}}

{{< tab "arangosh" >}}
```js
---
name: arangosh_cache_query_plan
description: ''
---
db._query("RETURN @val")
```
See the [JavaScript API](../../develop/javascript-api/@arangodb/db-object.md#db_createcollection-name--properties--type--options)
for details.
{{< /tab >}}

{{< tab "cURL" >}}
```sh
curl -d '{"query":"RETURN @val","bindVars":{"val":"5"},"options":{"usePlanCache":true}}' http://localhost:8529/_db/mydb/_api/cursor
```

See the [HTTP API](../../develop/http-api/queries/aql-query-plan-cache.md) for details. <!-- TODO: link to cursor API or query cache API? -->
{{< /tab >}}

{{< /tabs >}}

## Cache eligibility

<!-- TODO
LIMIT offset/count values must be constant numeric values - only raised if plan caching is on
-->
If plan caching is enabled for query, the eligibility for being cached is checked
first. Any queries that have any of the following query options set are not
eligible for plan caching:

- `allPlans`
- `optimizer.rules`
- `explainRegisters` (internal)
- `inaccessibleCollections` (internal)
- `shardIds` (internal)
Simran-B marked this conversation as resolved.
Show resolved Hide resolved

Additionally, a query is not eligible for plan caching if it uses attribute
name bind parameters (e.g. `FILTER doc.@attributeName == ...`) or when using
value bind parameters in any of the following places:
- Specifying the depths for traversals or path queries
(e.g. `FOR v, e IN @min..@max OUTBOUND ...`)
- Referring to a named graph (e.g. `GRAPH @graphName`)
- Referring to edge collections used in traversals or path queries
(e.g. `FOR v, e IN 1..2 OUTBOUND 'v/0' @@edgeColl ...`)

If a query produces any warnings during parsing or query plan optimization,
it is also not eligible for plan caching.

Query plans are also not eligible for caching if they contain one of the
following execution node types in the plan:
- `SingleRemoteOperationNode` (cluster only)
- `MultipleRemoteModificationNode` (cluster only)
- `UpsertNode`, i.e. the AQL `UPSERT` operation

If a query is eligible for plan caching, the plan cache is checked using
the exact same query string and set of collection bind parameter values.
A cached plan entry is only considered identical to the current query if the
query strings are identical byte for byte and the set of collection bind
parameters is exactly the same (bind parameter names and bind parameter
values).

If no plan entry can be found in the plan cache, the query is planned and
optimized as usual, and the cached plan is inserted into the plan cache.
Repeated executions of the same query (same query string and using the same
set of collection bind parameters) then makes use of the cached plan
entry, potentially with different value bind parameters.

The following query options are ignored when a cached plan is used:
- `joinStrategyType`
- `maxDNFConditionMembers`
- `maxNodesPerCallstack`

Whenever a query uses a plan from the plan cache, the query
result includes a `planCacheKey` attribute on the top level when
executing, explaining, or profiling a query. The explain and profiling
outputs also indicate when a cached query plan was used, showing
`plan cache key: ...` at the top.

## Cache invalidation
Simran-B marked this conversation as resolved.
Show resolved Hide resolved

The query plan cache is organized per database. It gets invalidated at the
following events:

- An existing collection gets dropped or renamed, or the properties of an
existing collection are modified
Simran-B marked this conversation as resolved.
Show resolved Hide resolved
- An index is added to an existing collection or an index is dropped
- An existing View gets dropped or renamed, or the properties of an existing
View are modified
- A named graph is added, or an existing named graph gets dropped

## Configuration

The memory usage of the query plan cache can be restricted using the following
startup options:

- [`--query.plan-cache-max-entries`](../../components/arangodb-server/options.md#--queryplan-cache-max-entries)
- [`--query.plan-cache-max-memory-usage`](../../components/arangodb-server/options.md#--queryplan-cache-max-memory-usage)
- [`--query.plan-cache-max-entry-size`](../../components/arangodb-server/options.md#--queryplan-cache-max-entry-size)
- [`--query.plan-cache-invalidation-time`](../../components/arangodb-server/options.md#--queryplan-cache-invalidation-time)

Note that each database has its own query plan cache, and that these options
are used for each individual plan cache. In a cluster, each Coordinator has its
own query plan cache.

## Interfaces

### List the query plan cache entries

Retrieve all entries in the query plan cache for the current database.

This requires read privileges for the current database. In addition, only those
query plans are returned for which the current user has at least read permissions
on all collections and Views included in the query.

{{< tabs "interfaces" >}}

{{< tab "arangosh" >}}
```js
const planCache = require("@arangodb/aql/plan-cache");
planCache.toArray();
```
{{< /tab >}}

{{< tab "cURL" >}}
```sh
curl http://localhost:8529/_api/query-plan-cache
```

See the [HTTP API](../../develop/http-api/queries/aql-query-plan-cache.md#list-the-entries-of-the-aql-query-plan-cache)
for details.
{{< /tab >}}

{{< /tabs >}}

### Clear the query plan cache

Delete all entries in the query plan cache for the current database.

This requires write privileges for the current database.

{{< tabs "interfaces" >}}

{{< tab "arangosh" >}}
```js
const planCache = require("@arangodb/aql/plan-cache");
planCache.clear();
```
{{< /tab >}}

{{< tab "cURL" >}}
```sh
curl -XDELETE http://localhost:8529/_api/query-plan-cache
```

See the [HTTP API](../../develop/http-api/queries/aql-query-plan-cache.md#clear-the-aql-query-results-cache)
for details.
{{< /tab >}}

{{< /tabs >}}
Loading