Skip to content
Merged
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
3 changes: 2 additions & 1 deletion TOC-tidb-cloud.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@
- [Wrong Index Solution](/wrong-index-solution.md)
- [Distinct Optimization](/agg-distinct-optimization.md)
- [Cost Model](/cost-model.md)
- [Prepare Execution Plan Cache](/sql-prepared-plan-cache.md)
- [Prepared Execution Plan Cache](/sql-prepared-plan-cache.md)
- [Non-Prepared Execution Plan Cache](/sql-non-prepared-plan-cache.md)
- Control Execution Plans
- [Overview](/control-execution-plan.md)
- [Optimizer Hints](/optimizer-hints.md)
Expand Down
3 changes: 2 additions & 1 deletion TOC.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,8 @@
- [Wrong Index Solution](/wrong-index-solution.md)
- [Distinct Optimization](/agg-distinct-optimization.md)
- [Cost Model](/cost-model.md)
- [Prepare Execution Plan Cache](/sql-prepared-plan-cache.md)
- [Prepared Execution Plan Cache](/sql-prepared-plan-cache.md)
- [Non-Prepared Execution Plan Cache](/sql-non-prepared-plan-cache.md)
- Control Execution Plans
- [Overview](/control-execution-plan.md)
- [Optimizer Hints](/optimizer-hints.md)
Expand Down
2 changes: 1 addition & 1 deletion latency-breakdown.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ e2e duration =

- `tidb_server_get_token_duration_seconds` records the duration of Token waiting. This is usually less than 1 millisecond and is small enough to be ignored.
- `tidb_session_parse_duration_seconds` records the duration of parsing SQL queries to an Abstract Syntax Tree (AST), which can be skipped by [`PREPARE/EXECUTE` statements](/develop/dev-guide-optimize-sql-best-practices.md#use-prepare).
- `tidb_session_compile_duration_seconds` records the duration of compiling an AST to an execution plan, which can be skipped by [SQL prepare execution plan cache](/sql-prepared-plan-cache.md).
- `tidb_session_compile_duration_seconds` records the duration of compiling an AST to an execution plan, which can be skipped by [SQL prepared execution plan cache](/sql-prepared-plan-cache.md).
- `tidb_session_execute_duration_seconds{type="general"}` records the duration of execution, which mixes all types of user queries. This needs to be broken down into fine-grained durations for analyzing performance issues or bottlenecks.

Generally, OLTP (Online Transactional Processing) workload can be divided into read and write queries, which share some critical code. The following sections describe latency in [read queries](#read-queries) and [write queries](#write-queries), which are executed differently.
Expand Down
Binary file added media/tidb-non-prepared-plan-cache-metrics.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
170 changes: 170 additions & 0 deletions sql-non-prepared-plan-cache.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
---
title: SQL Non-Prepared Execution Plan Cache
summary: Learn about the principle, usage, and examples of the SQL non-prepared execution plan cache in TiDB.
---

# SQL Non-Prepared Execution Plan Cache

> **Warning:**
>
> The non-prepared execution plan cache is an experimental feature. It is not recommended that you use it in the production environment. This feature might be changed or removed without prior notice. If you find a bug, you can report an [issue](https://github.com/pingcap/tidb/issues) on GitHub.

TiDB supports execution plan caching for some non-`PREPARE` statements, similar to the [`Prepare`/`Execute` statements](/sql-prepared-plan-cache.md). This feature allows these statements to skip the optimization phase and improve performance.

## Principle

The non-prepared plan cache is a session-level feature that is independent of the [prepared plan cache](/sql-prepared-plan-cache.md), and the cached plans do not affect each other. The basic principle of the non-prepared plan cache is as follows:

1. After you enable the non-prepared plan cache, TiDB first parameterizes the query based on the abstract syntax tree (AST). For example, `SELECT * FROM t WHERE b < 10 AND a = 1` is parameterized as `SELECT * FROM t WHERE b < ? and a = ?`.
2. Then, TiDB uses the parameterized query to search the non-prepared plan cache.
3. If a reusable plan is found, it is directly used and the optimization phase is skipped.
4. Otherwise, the optimizer generates a new plan and adds it back into the cache for reuse in the subsequent query.

## Usage

To enable or disable the non-prepared plan cache, you can set the [`tidb_enable_non_prepared_plan_cache`](/system-variables.md#tidb_enable_non_prepared_plan_cache) system variable. You can also control the size of the non-prepared plan cache using the [`tidb_non_prepared_plan_cache_size`](/system-variables.md#tidb_non_prepared_plan_cache_size) system variable. When the number of cached plans exceeds `tidb_non_prepared_plan_cache_size`, TiDB evicts plans using the least recently used (LRU) strategy.

## Example

The following example shows how to use the non-prepared plan cache:

1. Create a table `t` for testing:

```sql
CREATE TABLE t (a INT, b INT, KEY(b));
```

2. Enable the non-prepared plan cache:

```sql
SET tidb_enable_non_prepared_plan_cache = true;
```

3. Execute the following two queries:

```sql
SELECT * FROM t WHERE b < 10 AND a = 1;
SELECT * FROM t WHERE b < 5 AND a = 2;
```

4. Check whether the second query hits the cache:

```sql
SELECT @@last_plan_from_cache;
```

If the value of `last_plan_from_cache` in the output is `1`, it means that the execution plan of the second query comes from the cache:

```sql
+------------------------+
| @@last_plan_from_cache |
+------------------------+
| 1 |
+------------------------+
1 row in set (0.00 sec)
```

## Restrictions

TiDB only caches one plan for a parameterized query. For example, the queries `SELECT * FROM t WHERE a < 1` and `SELECT * FROM t WHERE a < 100000` share the same parameterized form, `SELECT * FROM t WHERE a < ?`, and thus share the same plan.

If this causes performance issues, you can use the `ignore_plan_cache()` hint to ignore plans in the cache, so that the optimizer generates a new execution plan for the SQL every time. If the SQL cannot be modified, you can create a binding to solve the problem. For example, `CREATE BINDING FOR SELECT ... USING SELECT /*+ ignore_plan_cache() */ ...`.

Due to the preceding risks and the fact that the execution plan cache only provides significant benefits for simple queries (if a query is complex and takes a long time to execute, using the execution plan cache might not be very helpful), TiDB has strict restrictions on the scope of non-prepared plan cache. The restrictions are as follows:

- Queries or plans that are not supported by the [Prepared plan cache](/sql-prepared-plan-cache.md) are also not supported by the non-prepared plan cache.
- Currently, only point get or range queries on a single table that contain `Scan`, `Selection`, or `Projection` operators are supported, such as `SELECT * FROM t WHERE a < 10 AND b in (1, 2)`.
- Queries that contain complex operators such as `Agg`, `Limit`, `Window`, or `Sort` are not supported.
- Queries that contain non-range query conditions are not supported, such as:
- `LIKE` is not supported, such as `c LIKE 'c%'`.
- `+` operation is not supported, such as `a+1 < 2`.
- Queries that filter on columns of `JSON`, `ENUM`, `SET`, or `BIT` type are not supported, such as `SELECT * FROM t WHERE json_col = '{}'`.
- Queries that filter on `NULL` values are not supported, such as `SELECT * FROM t WHERE a is NULL`.
- Queries with more than 50 parameters after parameterization are not supported, such as `SELECT * FROM t WHERE a in (1, 2, 3, ... 51)`.
- Queries that access partitioned tables, virtual columns, temporary tables, views, or memory tables are not supported, such as `SELECT * FROM INFORMATION_SCHEMA.COLUMNS`, where `COLUMNS` is a TiDB memory table.
- Queries with hints, subqueries, or locks are not supported.
- DML statements are not supported.

## Diagnostics

After enabling the non-prepared plan cache, you can execute the `EXPLAIN FORMAT='plan_cache' SELECT ...` statement to verify whether the query can hit the cache. For queries that cannot hit the cache, the system returns the reason in a warning.

Note that if you do not add `FORMAT='plan_cache'`, the `EXPLAIN` statement will never hit the cache.

To verify whether the query hits the cache, execute the following `EXPLAIN FORMAT='plan_cache'` statement:

```sql
EXPLAIN FORMAT='plan_cache' SELECT * FROM t WHERE a+2 < 10;
```

The output is as follows:

```sql
3 rows in set, 1 warning (0.00 sec)
```

To view the queries that cannot hit the cache, execute `SHOW warnings;`:

```sql
SHOW warnings;
```

The output is as follows:

```sql
+---------+------+-----------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+-----------------------------------------------------------------------+
| Warning | 1105 | skip non-prep plan cache: query has some unsupported binary operation |
+---------+------+-----------------------------------------------------------------------+
1 row in set (0.00 sec)
```

In the preceding example, the query cannot hit the cache because the non-prepared plan cache does not support the `+` operation.

## Monitoring

After enabling the non-prepared plan cache, you can monitor the memory usage, number of plans in the cache, and cache hit rate in the following panes:

![non-prepare-plan-cache](/media/tidb-non-prepared-plan-cache-metrics.png)

You can also monitor the cache hit rate in the `statements_summary` table and slow query log. The following shows how to view the cache hit rate in the `statements_summary` table:

1. Create a table `t`:

```sql
CREATE TABLE t (a int);
```

2. Enable the non-prepared plan cache:

```sql
SET @@tidb_enable_non_prepared_plan_cache=1;
```

3. Execute the following three queries:

```sql
SELECT * FROM t WHERE a<1;
SELECT * FROM t WHERE a<2;
SELECT * FROM t WHERE a<3;
```

4. Query the `statements_summary` table to view the cache hit rate:

```sql
SELECT digest_text, query_sample_text, exec_count, plan_in_cache, plan_cache_hits FROM INFORMATION_SCHEMA.STATEMENTS_SUMMARY WHERE digest_text LIKE '%SELECT * FROM %';
```

The output is as follows:

```sql
+---------------------------------+------------------------------------------+------------+---------------+-----------------+
| digest_text | query_sample_text | exec_count | plan_in_cache | plan_cache_hits |
+---------------------------------+------------------------------------------+------------+---------------+-----------------+
| SELECT * FROM `t` WHERE `a` < ? | SELECT * FROM t WHERE a<1 [arguments: 1] | 3 | 1 | 2 |
+---------------------------------+------------------------------------------+------------+---------------+-----------------+
1 row in set (0.01 sec)
```

From the output, you can see that the query was executed three times and hit the cache twice.
6 changes: 3 additions & 3 deletions sql-prepared-plan-cache.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
---
title: SQL Prepare Execution Plan Cache
summary: Learn about SQL Prepare Execution Plan Cache in TiDB.
title: SQL Prepared Execution Plan Cache
summary: Learn about SQL Prepared Execution Plan Cache in TiDB.
aliases: ['/tidb/dev/sql-prepare-plan-cache']
---

# SQL Prepare Execution Plan Cache
# SQL Prepared Execution Plan Cache

TiDB supports execution plan caching for `Prepare` and `Execute` queries. This includes both forms of prepared statements:

Expand Down
8 changes: 4 additions & 4 deletions system-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -1513,13 +1513,13 @@ MPP is a distributed computing framework provided by the TiFlash engine, which a

> **Warning:**
>
> The feature controlled by this variable is not fully functional in the current TiDB version. Do not change the default value.
> The non-prepared execution plan cache is an experimental feature. It is not recommended that you use it in the production environment. This feature might be changed or removed without prior notice. If you find a bug, you can report an [issue](https://github.com/pingcap/tidb/issues) on GitHub.

- Scope: SESSION | GLOBAL
- Persists to cluster: Yes
- Type: Boolean
- Default value: `OFF`
- This variable controls whether to enable the General Plan Cache feature.
- This variable controls whether to enable the [Non-prepared plan cache](/sql-non-prepared-plan-cache.md) feature.

### tidb_enable_gogc_tuner <span class="version-mark">New in v6.4.0</span>

Expand Down Expand Up @@ -2277,14 +2277,14 @@ For a system upgraded to v5.0 from an earlier version, if you have not modified

> **Warning:**
>
> The feature controlled by this variable is not fully functional in the current TiDB version. Do not change the default value.
> The non-prepared execution plan cache is an experimental feature. It is not recommended that you use it in the production environment. This feature might be changed or removed without prior notice. If you find a bug, you can report an [issue](https://github.com/pingcap/tidb/issues) on GitHub.

- Scope: SESSION | GLOBAL
- Persists to cluster: Yes
- Type: Integer
- Default value: `100`
- Range: `[1, 100000]`
- This variable controls the maximum number of execution plans that can be cached by General Plan Cache.
- This variable controls the maximum number of execution plans that can be cached by [Non-prepared plan cache](/sql-non-prepared-plan-cache.md).

### tidb_generate_binary_plan <span class="version-mark">New in v6.2.0</span>

Expand Down
2 changes: 1 addition & 1 deletion tidb-cloud/tidb-cloud-sql-tuning-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ After parsing the original query text by `parser` and basic validity verificatio

Through these equivalence changes, the query can become easier to handle in the logical execution plan. After the equivalence changes, TiDB gets a query plan structure that is equivalent to the original query, and then gets a final execution plan based on the data distribution and the specific execution overhead of an operator. For more information, see [SQL Physical Optimization](/sql-physical-optimization.md).

Also, TiDB can choose to enable execution plan cache to reduce the creation overhead of the execution plan when executing the `PREPARE` statement, as introduced in [Prepare Execution Plan Cache](/sql-prepared-plan-cache.md).
Also, TiDB can choose to enable execution plan cache to reduce the creation overhead of the execution plan when executing the `PREPARE` statement, as introduced in [Prepared Execution Plan Cache](/sql-prepared-plan-cache.md).

### Optimize full table scan

Expand Down