diff --git a/TOC-tidb-cloud.md b/TOC-tidb-cloud.md
index d6ba4ecbd2253..a31ea81de0786 100644
--- a/TOC-tidb-cloud.md
+++ b/TOC-tidb-cloud.md
@@ -200,8 +200,7 @@
- [Distinct Optimization](/agg-distinct-optimization.md)
- [Cost Model](/cost-model.md)
- [Runtime Filter](/runtime-filter.md)
- - [Prepared Execution Plan Cache](/sql-prepared-plan-cache.md)
- - [Non-Prepared Execution Plan Cache](/sql-non-prepared-plan-cache.md)
+ - [SQL Plan Cache](/sql-plan-cache.md)
- Control Execution Plans
- [Overview](/control-execution-plan.md)
- [Optimizer Hints](/optimizer-hints.md)
diff --git a/TOC.md b/TOC.md
index 0ebfe61be7a87..3ec917a435dbd 100644
--- a/TOC.md
+++ b/TOC.md
@@ -362,8 +362,7 @@
- [Distinct Optimization](/agg-distinct-optimization.md)
- [Cost Model](/cost-model.md)
- [Runtime Filter](/runtime-filter.md)
- - [Prepared Execution Plan Cache](/sql-prepared-plan-cache.md)
- - [Non-Prepared Execution Plan Cache](/sql-non-prepared-plan-cache.md)
+ - [SQL Plan Cache](/sql-plan-cache.md)
- Control Execution Plans
- [Overview](/control-execution-plan.md)
- [Optimizer Hints](/optimizer-hints.md)
diff --git a/basic-features.md b/basic-features.md
index 05aa8b0d0099c..fdb7ee4b1a1fc 100644
--- a/basic-features.md
+++ b/basic-features.md
@@ -99,9 +99,7 @@ You can try out TiDB features on [TiDB Playground](https://play.tidbcloud.com/?u
| Advanced SQL features | 8.5 | 8.1 | 7.5 | 7.1 | 6.5 | 6.1 | 5.4 | 5.3 | 5.2 | 5.1 |
|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| [Vector search](/vector-search/vector-search-overview.md) | E | N | N | N | N | N | N | N | N | N |
-| [Prepared statement cache](/sql-prepared-plan-cache.md) | Y | Y | Y | Y | Y | Y | Y | Y | E | E |
-| [Non-prepared statement cache](/sql-non-prepared-plan-cache.md) | Y | Y | Y | E | N | N | N | N | N | N |
-| [Instance-level execution plan cache](/system-variables.md#tidb_enable_instance_plan_cache-new-in-v840) | E | N | N | N | N | N | N | N | N | N |
+| [SQL Plan cache](/sql-plan-cache.md) | Y | Y | Y | Y | Y | Y | Y | Y | E | E |
| [SQL binding](/sql-plan-management.md#sql-binding) | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
| [Cross-database binding](/sql-plan-management.md#cross-database-binding) | Y | Y | N | N | N | N | N | N | N | N |
| [Create bindings according to historical execution plans](/sql-plan-management.md#create-a-binding-according-to-a-historical-execution-plan) | Y | Y | Y | Y | E | N | N | N | N | N |
diff --git a/benchmark/benchmark-tidb-using-sysbench.md b/benchmark/benchmark-tidb-using-sysbench.md
index f821bdb1ff03f..c218b61b1e1fb 100644
--- a/benchmark/benchmark-tidb-using-sysbench.md
+++ b/benchmark/benchmark-tidb-using-sysbench.md
@@ -20,7 +20,7 @@ server_configs:
log.level: "error"
```
-It is also recommended to make sure [`tidb_enable_prepared_plan_cache`](/system-variables.md#tidb_enable_prepared_plan_cache-new-in-v610) is enabled and that you allow sysbench to use prepared statements by using `--db-ps-mode=auto`. See the [SQL Prepared Execution Plan Cache](/sql-prepared-plan-cache.md) for documentation about what the SQL plan cache does and how to monitor it.
+It is also recommended to make sure [`tidb_enable_prepared_plan_cache`](/system-variables.md#tidb_enable_prepared_plan_cache-new-in-v610) is enabled and that you allow sysbench to use prepared statements by using `--db-ps-mode=auto`. See the [SQL Prepared Execution Plan Cache](/sql-plan-cache.md) for documentation about what the SQL plan cache does and how to monitor it.
> **Note:**
>
diff --git a/latency-breakdown.md b/latency-breakdown.md
index 56fb881e7faf1..50e921a9d901c 100644
--- a/latency-breakdown.md
+++ b/latency-breakdown.md
@@ -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 prepared 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-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.
diff --git a/media/plancache-session-instance-comparison.PNG b/media/plancache-session-instance-comparison.PNG
new file mode 100644
index 0000000000000..509b760b5ba45
Binary files /dev/null and b/media/plancache-session-instance-comparison.PNG differ
diff --git a/optimizer-fix-controls.md b/optimizer-fix-controls.md
index 0d0b905a07cbe..59172d1c5eb24 100644
--- a/optimizer-fix-controls.md
+++ b/optimizer-fix-controls.md
@@ -30,7 +30,7 @@ SET SESSION tidb_opt_fix_control = '44262:ON,44389:ON';
- Default value: `OFF`
- Possible values: `ON`, `OFF`
-- This variable controls whether to allow plan cache for partitioned tables. If it is set to `ON`, neither [Prepared statement plan cache](/sql-prepared-plan-cache.md) nor [Non-prepared statement plan cache](/sql-non-prepared-plan-cache.md) will be enabled for [partitioned tables](/partitioned-table.md).
+- This variable controls whether to allow plan cache for partitioned tables. If it is set to `ON`, neither [Prepared statement plan cache](/sql-plan-cache.md) nor [Non-prepared statement plan cache](/sql-plan-cache.md) will be enabled for [partitioned tables](/partitioned-table.md).
### [`44262`](https://github.com/pingcap/tidb/issues/44262) New in v6.5.3 and v7.2.0
diff --git a/optimizer-hints.md b/optimizer-hints.md
index d3468c85f89f7..2e6118ee14b99 100644
--- a/optimizer-hints.md
+++ b/optimizer-hints.md
@@ -771,7 +771,7 @@ In addition to this hint, setting the `tidb_replica_read` environment variable t
The `IGNORE_PLAN_CACHE()` hint reminds the optimizer not to use the Plan Cache when handling the current `prepare` statement.
-This hint is used to temporarily disable the Plan Cache for a certain type of queries when [prepare-plan-cache](/sql-prepared-plan-cache.md) is enabled.
+This hint is used to temporarily disable the Plan Cache for a certain type of queries when [prepare-plan-cache](/sql-plan-cache.md) is enabled.
In the following example, the Plan Cache is forcibly disabled when executing the `prepare` statement.
diff --git a/performance-tuning-methods.md b/performance-tuning-methods.md
index 45c7d746f8d07..04c74c9267f82 100644
--- a/performance-tuning-methods.md
+++ b/performance-tuning-methods.md
@@ -137,7 +137,7 @@ The diagrams of database time breakdown and execution time overview present both
#### Query Per Second, Command Per Second, and Prepared-Plan-Cache
-By checking the following three panels in Performance Overview, you can learn the application workload type, how the application interacts with TiDB, and whether the application fully utilizes TiDB [prepared plan cache](/sql-prepared-plan-cache.md).
+By checking the following three panels in Performance Overview, you can learn the application workload type, how the application interacts with TiDB, and whether the application fully utilizes TiDB [prepared plan cache](/sql-plan-cache.md).
- QPS: Short for Query Per Second. It shows the count of SQL statements executed by the application.
- CPS By Type: Short for Command Per Second. Command indicates MySQL protocol-specific commands. A query statement can be sent to TiDB either by a query command or a prepared statement.
@@ -148,7 +148,7 @@ By checking the following three panels in Performance Overview, you can learn th
- No prepared plan cache is hit: `avg-hit` (the number of hits per second) is 0, and `avg-miss` is equal to the number of `StmtExecute` commands per second. The possible reasons include:
- The application is using the query interface.
- The cached plans are cleaned up because the application calls the `StmtClose` command after each `StmtExecute` execution.
- - All statements executed by `StmtExecute` do not meet the [cache conditions](/sql-prepared-plan-cache.md) so the execution plan cache cannot be hit.
+ - All statements executed by `StmtExecute` do not meet the [cache conditions](/sql-plan-cache.md) so the execution plan cache cannot be hit.
- All prepared plan cache is hit: `avg-hit` (the number of hits per second) is equal to the number of `StmtExecute` commands per second, and `avg-miss` (the number without hits per second) is 0.
- Some prepared plan cache is hit: `avg-hit` (the number of hits per second) is fewer than the number of `StmtExecute` commands per second. Prepared plan cache has known limitations. For example, it does not support subqueries, so SQL statements with subqueries cannot use prepared plan cache.
diff --git a/sql-non-prepared-plan-cache.md b/sql-non-prepared-plan-cache.md
deleted file mode 100644
index 1378361f75c97..0000000000000
--- a/sql-non-prepared-plan-cache.md
+++ /dev/null
@@ -1,188 +0,0 @@
----
-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
-
-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.
-
-Enabling the non-prepared plan cache might incur additional memory and CPU overhead and might not be suitable for all situations. To determine whether to enable this feature in your scenario, refer to the [Performance benefits](#performance-benefits) and [Memory monitoring](#monitoring) sections.
-
-## Principle
-
-The non-prepared plan cache is a session-level feature that shares a cache with the [prepared plan cache](/sql-prepared-plan-cache.md). 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 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_session_plan_cache_size`](/system-variables.md#tidb_session_plan_cache_size-new-in-v710) system variable. When the number of cached plans exceeds `tidb_session_plan_cache_size`, TiDB evicts plans using the least recently used (LRU) strategy.
-
-Starting from v7.1.0, you can control the maximum size of a plan that can be cached using the system variable [`tidb_plan_cache_max_plan_size`](/system-variables.md#tidb_plan_cache_max_plan_size-new-in-v710). The default value is 2 MB. If the size of a plan exceeds this value, the plan will not be cached.
-
-> **Note:**
->
-> The memory specified by `tidb_session_plan_cache_size` is shared between the prepared and non-prepared plan cache. If you have enabled the prepared plan cache for the current cluster, enabling the non-prepared plan cache might reduce the hit rate of the original prepared plan cache.
-
-## 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 = ON;
- ```
-
-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
-
-### Cache suboptimal plans
-
-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() */ ...`.
-
-### Usage restrictions
-
-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.
-- Queries that contain complex operators such as `Window` or `Having` are not supported.
-- Queries that contain three or more `Join` tables or subqueries are not supported.
-- Queries that contain numbers or expressions directly after `ORDER BY` or `GROUP BY` are not supported, such as `ORDER BY 1` and `GROUP BY a+1`. Only `ORDER BY column_name` and `GROUP BY column_name` are supported.
-- 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 200 parameters after parameterization are not supported by default, such as `SELECT * FROM t WHERE a in (1, 2, 3, ... 201)`. Starting from v7.3.0, you can modify this limit by setting the [`44823`](/optimizer-fix-controls.md#44823-new-in-v730) fix in the [`tidb_opt_fix_control`](/system-variables.md#tidb_opt_fix_control-new-in-v653-and-v710) system variable.
-- Queries that access 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 or bindings are not supported.
-- DML statements or `SELECT` statements with the `FOR UPDATE` clause are not supported by default. To remove this restriction, you can execute `SET tidb_enable_non_prepared_plan_cache_for_dml = ON`.
-
-After you enable this feature, the optimizer quickly evaluates the query. If it does not meet the support conditions for non-prepared plan cache, the query falls back to the regular optimization process.
-
-## Performance benefits
-
-In internal tests, enabling the non-prepared plan cache feature can achieve significant performance benefits in most TP scenarios. For example, a performance improvement of about 4% in TPC-C tests, over 10% in some banking workloads, and 15% in Sysbench RangeScan.
-
-However, this feature also introduces some additional memory and CPU overhead, including determining whether the query is supported, parameterizing the query, and searching for a plan in the cache. If the cache cannot hit the majority of queries in your workload, enabling it might actually adversely affect performance.
-
-In this case, you need to observe the `non-prepared` metric in the **Queries Using Plan Cache OPS** panel and the `non-prepared-unsupported` metric in the **Plan Cache Miss OPS** panel on Grafana. If most queries are not supported and only a few can hit the plan cache, you can disable this feature.
-
-![non-prepared-unsupported](/media/non-prepapred-plan-cache-unsupprot.png)
-
-## 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 (SELECT a+1 FROM t) t;
-```
-
-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-prepared plan-cache: queries that have sub-queries are not supported |
-+---------+------+-------------------------------------------------------------------------------+
-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=ON;
- ```
-
-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 query_sample_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 | 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.
diff --git a/sql-optimization-concepts.md b/sql-optimization-concepts.md
index e1c8935f02eae..9af0b83174312 100644
--- a/sql-optimization-concepts.md
+++ b/sql-optimization-concepts.md
@@ -14,4 +14,4 @@ After parsing the original query text by `parser` and some simple validity check
Through these equivalent changes, this query becomes easier to handle in the logical execution plan. After the equivalent change is done, TiDB obtains a query plan structure equivalent to the original query, and then obtains a final execution plan based on the data distribution and the specific execution cost of an operator. For details, see [SQL Physical Optimization](/sql-physical-optimization.md).
-At the same time, when TiDB executes the [`PREPARE`](/sql-statements/sql-statement-prepare.md) statement, you can choose to enable caching to reduce the cost of generating the execution plan in TiDB. For details, see [Execution Plan Cache](/sql-prepared-plan-cache.md).
\ No newline at end of file
+At the same time, when TiDB executes the [`PREPARE`](/sql-statements/sql-statement-prepare.md) statement, you can choose to enable caching to reduce the cost of generating the execution plan in TiDB. For details, see [Execution Plan Cache](/sql-plan-cache.md).
\ No newline at end of file
diff --git a/sql-plan-cache.md b/sql-plan-cache.md
new file mode 100644
index 0000000000000..e1373d1225070
--- /dev/null
+++ b/sql-plan-cache.md
@@ -0,0 +1,397 @@
+---
+title: SQL Plan Cache
+summary: Learn about SQL Plan Cache in TiDB.
+aliases: ['/tidb/dev/sql-plan-cache']
+---
+
+# Introduction
+
+TiDB supports using Plan Cache to cache execution plans in memory and reuse them for the same queries, which avoids repeatedly compiling plans and brings some performance improvements.
+
+TiDB supports both Session Plan Cache and Instance Plan Cache. Session Plan Cache maintains cache for each session, plans can't be shared across different sessions, while Instance Plan Cache maintains one single cache in the instance for all sessions.
+
+We recommend you to use Plan Cache with `Prepare/Execute` statements or `COM_STMT_PREPARE/EXECUTE` protocol, but for normal Non-Prepared statements, TiDB also support Non-Prepared Plan Cache.
+
+# Usage
+
+## Use Session Plan Cache
+
+To enable Session Plan Cache, you need to set `tidb_enable_prepared_plan_cache` to true and set `tidb_enable_instance_plan_cache` to false.
+
+And you can use `@@last_plan_from_cach` to check whether the last statement hits the Plan Cache:
+
+```sql
+myaql> set global tidb_enable_prepared_plan_cache=1;
+Query OK, 0 rows affected (0.00 sec)
+
+myaql> set global tidb_enable_instance_plan_cache=0;
+Query OK, 0 rows affected (0.00 sec)
+
+mysql> prepare st from "select a from t";
+Query OK, 0 rows affected (0.00 sec)
+
+mysql> execute st;
+Empty set (0.00 sec)
+
+mysql> execute st;
+Empty set (0.00 sec)
+
+mysql> select @@last_plan_from_cache;
++------------------------+
+| @@last_plan_from_cache |
++------------------------+
+| 1 |
++------------------------+
+```
+
+## Use Instance Plan Cache
+
+> **Warning:**
+>
+> Instance Plan Cache is an experimental feature.
+
+TiDB starts supporting Instance Plan Cache after v8.4.
+
+To enable Instance Plan Cache, you need to set `tidb_enable_prepared_plan_cache` to true and set `tidb_enable_instance_plan_cache` to true.
+
+Cached plans can shared across different sessions when enabling this feature:
+
+```sql
+-- execute below SQLs in session-1
+mysql> set global tidb_enable_instance_plan_cache=1;
+Query OK, 0 rows affected (0.01 sec)
+
+mysql> prepare st from "select a from t";
+Query OK, 0 rows affected (0.01 sec)
+
+mysql> execute st;
+Empty set (0.00 sec)
+
+-- execute below SQLs in session-2
+mysql> prepare st from "select a from t";
+Query OK, 0 rows affected (0.00 sec)
+
+mysql> execute st;
+Empty set (0.00 sec)
+
+mysql> select @@last_plan_from_cache;
++------------------------+
+| @@last_plan_from_cache |
++------------------------+
+| 1 |
++------------------------+
+```
+
+## Comparison of Session and Instance Plan Cache
+Session Plan Cache means each session has its own Plan Cache, for example, if there are 10 sessions executing the same query `select a from t`, then there are 10 same plans cached in memory. In the opposite, if you are using Instance Plan Cache, then there is only 1 plan cached in memory for this query.
+
+Session Plan Cache has a slightly better performance (around 1~3%), but incurs more memory usage. Below is a test based on Sysbench-oltp_read_only with 120 concurrency, where Session Plan Cache costs more than 1GB memory usage while Instance Plan Cache only costs 58MB.
+
+![comparison](/media/plancache-session-instance-comparison.PNG)
+
+## Non-Prepared Plan Cache
+
+Set `tidb_enable_non_prepared_plan_cache` to true to enable this feature:
+
+```sql
+mysql> SET tidb_enable_non_prepared_plan_cache = ON;
+Query OK, 0 rows affected (0.00 sec)
+
+mysql> select * from t where a<10 and b=1;
+Empty set (0.01 sec)
+
+mysql> select * from t where a<20 and b=20;
+Empty set (0.00 sec)
+
+mysql> select @@last_plan_from_cache;
++------------------------+
+| @@last_plan_from_cache |
++------------------------+
+| 1 |
++------------------------+
+```
+
+Non-Prepared Plan Cache needs to parameterizes the query (for example, parameterize `SELECT * FROM t WHERE b < 10 AND a = 1` to `SELECT * FROM t WHERE b < ? and a = ?`) and use it to search the plan cache, which might incur additional overhead, so it's not suitable for all situations. Please decide whether to use this feature according to your workload.
+
+# Management and diagnosis of Plan Cache
+
+## Related Metrics
+
+In [the Grafana dashboard](/grafana-tidb-dashboard.md) on the TiDB page in the Executor section, there are the Queries Using Plan Cache OPS and Plan Cache Miss OPS graphs, and they can help you to know the number quereis can and can't hit Plan Cache:
+
+![`sql_plan_cache`](/media/performance/sql_plan_cache.png)
+
+To view the total memory consumption by the cached execution plans of all sessions in each TiDB instance, you can use [**Plan Cache Memory Usage** monitoring panel](/grafana-tidb-dashboard.md) in Grafana.
+
+To view the total number of execution plans cached in each TiDB instance, you can use [**Plan Cache Plan Num** panel](/grafana-tidb-dashboard.md) in Grafana.
+
+The following is an example of the Plan Cache Memory Usage and Plan Cache Plan Num panels in Grafana:
+
+![grafana_panels](/media/planCache-memoryUsage-planNum-panels.png)
+
+## Memory Usage Management
+
+### Session Plan Cache
+
+Starting from v7.1.0, you can control the maximum number of plans that can be cached in each session by configuring the system variable [`tidb_session_plan_cache_size`](/system-variables.md#tidb_session_plan_cache_size-new-in-v710). For different environments, the recommended value is as follows and you can adjust it according to the monitoring panels:
+
+- When the memory threshold of the TiDB server instance is <= 64 GiB, set `tidb_session_plan_cache_size` to 50.
+- When the memory threshold of the TiDB server instance is > 64 GiB, set `tidb_session_plan_cache_size` to 100.
+
+Starting from v7.1.0, you can control the maximum size of a plan that can be cached using the system variable [`tidb_plan_cache_max_plan_size`](/system-variables.md#tidb_plan_cache_max_plan_size-new-in-v710). The default value is 2 MB. If the size of a plan exceeds this value, the plan will not be cached.
+
+When the unused memory of the TiDB server is less than a certain threshold, the memory protection mechanism of plan cache is triggered, through which some cached plans will be evicted.
+
+You can control the threshold by configuring the system variable `tidb_prepared_plan_cache_memory_guard_ratio`. The threshold is 0.1 by default, which means when the unused memory of the TiDB server is less than 10% of the total memory (90% of the memory is used), the memory protection mechanism is triggered.
+
+### Instance Plan Cache
+
+Use `tidb_instance_plan_cache_max_size` to set the total memory limitation of Instance Plan Cache. For example, `set global tidb_instance_plan_cache_max_size=200MiB` .
+
+TiDB purges the Instance Plan Cache periodically, and you can set `tidb_instance_plan_cache_reserved_percentage` to control the amount of memory to purge each time. For example, the default percentage is `0.1`, and if the max size is `200MiB`, then TiDB purges `200*0.1=20MiB` memory each time.
+
+## Why the query can't hit Plan Cache
+
+Optimzier outputs the reason why the current query can't hit Plan Cache as warnings, so you can use `SHOW WARNINGS` statement to check the reason:
+
+```sql
+mysql> PREPARE st FROM 'SELECT * FROM t WHERE a > (SELECT MAX(a) FROM t)'; -- The query contains a subquery and cannot be cached.
+Query OK, 0 rows affected, 1 warning (0.01 sec)
+
+mysql> SHOW WARNINGS; -- Checks the reason why the query plan cannot be cached.
++---------+------+-----------------------------------------------+
+| Level | Code | Message |
++---------+------+-----------------------------------------------+
+| Warning | 1105 | skip plan-cache: sub-queries are un-cacheable |
++---------+------+-----------------------------------------------+
+1 row in set (0.00 sec)
+
+mysql> prepare st from 'select * from t where a';
+Query OK, 0 rows affected (0.00 sec)
+
+mysql> set @a='1';
+Query OK, 0 rows affected (0.00 sec)
+
+mysql> execute st using @a; -- The optimization converts a non-INT type to an INT type, and the execution plan might change with the change of the parameter, so TiDB does not cache the plan.
+Empty set, 1 warning (0.01 sec)
+
+mysql> SHOW WARNINGS;
++---------+------+----------------------------------------------+
+| Level | Code | Message |
++---------+------+----------------------------------------------+
+| Warning | 1105 | skip plan-cache: '1' may be converted to INT |
++---------+------+----------------------------------------------+
+1 row in set (0.00 sec)
+```
+
+## Which queries can't hit Plan Cache in your workload
+
+The `Statements Summary` table contains two fields, `plan_cache_unqualified` and `plan_cache_unqualified_last_reason`, which respectively indicate the number of times and the reason why the corresponding query is unable to use the plan cache.
+
+You can use these two fields for diagnostic purposes:
+
+```sql
+mysql> SELECT digest_text, plan_cache_unqualified, plan_cache_unqualified_last_reason
+ FROM information_schema.statements_summary
+ WHERE plan_cache_unqualified > 0 ORDER BY plan_cache_unqualified DESC
+ LIMIT 10;
++---------------------------------+------------------------+----------------------------------------+
+| digest_text | plan_cache_unqualified | plan_cache_unqualified_last_reason |
++---------------------------------+------------------------+----------------------------------------+
+| select * from `t` where `a` < ? | 10 | '1' may be converted to INT |
+| select * from `t` order by ? | 4 | query has 'order by ?' is un-cacheable |
+| select database ( ) from `t` | 2 | query has 'database()' is un-cacheable |
+...
++---------------------------------+------------------------+----------------------------------------+
+```
+
+## Cached Plans in Instance Plan Cache
+
+For Instance Plan Cache, TiDB provides 2 system views (after v8.5) `information_schema.tidb_plan_cache` and `information_schema.cluster_tidb_plan_cache` to see the internal information of the Instance Plan Cache of the current instance and the whole cluster:
+
+```sql
+mysql> select *, tidb_decode_binary_plan(binary_plan) from information_schema.tidb_plan_cache\G;
+*************************** 1. row ***************************
+ SQL_DIGEST: 3689d7f367e2fdaf53c962c378efdf47799143b9af12f47e13ec247332269eac
+ SQL_TEXT: select a from t where a
+ STMT_TYPE: Select
+ PARSE_USER: root
+ PLAN_DIGEST: 6285ba7cabe7b19459668d62ec201ecbea63ac5f23e5b9166f02fbb86cdf4807
+ BINARY_PLAN: iQKYCoYCCg1UYWJsZVJlYWRlcl83ErYBCgtTZWxlY3Rpb25fNhJqCg9UASFMRnVsbFNjYW5fNSEAAAAAiKFSQSkBCeAAiMNAOAJAAkoLCgkKBHRlc3QSAXRSHmtlZXAgb3JkZXI6ZmFsc2UsIHN0YXRzOnBzZXVkb3D///8JAgQBeAkIDP///wEFWSzWiFRBKauqqqqq9qkFWRBSD2x0KAFYHC50LmEsIDEpWj0AGE8b6LShwhYdPSQBQAFSEGRhdGE6HdFWPgA=
+ BINDING:
+ OPT_ENV: f20c20a72b2a33c5c44e805dbea0fa97028e6f047320928cf367f74c8c94737b
+ PARSE_VALUES: 1
+ MEM_SIZE: 13322
+ EXECUTIONS: 1
+ PROCESSED_KEYS: 0
+ TOTAL_KEYS: 0
+ SUM_LATENCY: 5919417
+ LOAD_TIME: 2024-12-05 15:41:43
+ LAST_ACTIVE_TIME: 2024-12-05 15:41:43
+tidb_decode_binary_plan(binary_plan):
+| id | estRows | estCost | task | access object | operator info |
+| TableReader_7 | 3323.33 | 372904.43 | root | | data:Selection_6 |
+| └─Selection_6 | 3323.33 | 5383000.00 | cop[tikv] | | lt(test.t.a, 1) |
+| └─TableFullScan_5 | 10000.00 | 4884000.00 | cop[tikv] | table:t | keep order:false, stats:pseudo |
+
+*************************** 2. row ***************************
+ SQL_DIGEST: e46ac1d144fbf88c80d4eb9eeb43e8c57d92ed6cb7a6afbbe37a3f7651fa9446
+ SQL_TEXT: select a from t where a=? and b=?
+ STMT_TYPE: Select
+ PARSE_USER: root
+ PLAN_DIGEST: 88a275584ffbf1f6ae20629c677efecc8dc2bb3ec02f8a5859323d7755a4ff22
+ BINARY_PLAN: 5AKwCuECCg5UYWJsZVJlYWRlcl8xMRKPAgoMUHJvamVjdGlvbl81EsgBCgxTZWxlCRAUMTASagoPBTRMRnVsbFNjYW5fOSEAAAAAiKFSQSkBCeAAiMNAOAJAAkoLCgkKBHRlc3QSAXRSHmtlZXAgb3JkZXI6ZmFsc2UsIHN0YXRzOnBzZXVkb3D///8JAgQBeAkIDP///wEFWTAkcFZBKXsUrkfheoQ/AVkQUiBlcSgBWCAudC5hLCAxKSwdEQBiARFaTgAM6lkQAEZOAAAIEUtaNgAYhEEHaxXvFx2EJAFAAVIRZGF0YTouKgFWPwA=
+ BINDING:
+ OPT_ENV: 88676ae6596aa2968e2ddd45ec0756ca71e7ccc3f3d16f6f3e4db4737335af2c
+ PARSE_VALUES: (1, 1)
+ MEM_SIZE: 19630
+ EXECUTIONS: 7
+ PROCESSED_KEYS: 0
+ TOTAL_KEYS: 0
+ SUM_LATENCY: 9134791
+ LOAD_TIME: 2024-12-05 15:41:56
+ LAST_ACTIVE_TIME: 2024-12-05 15:42:02
+tidb_decode_binary_plan(binary_plan):
+| id | estRows | estCost | task | access object | operator info |
+| TableReader_11 | 0.01 | 392133.35 | root | | data:Projection_5 |
+| └─Projection_5 | 0.01 | 5882000.00 | cop[tikv] | | test.t.a |
+| └─Selection_10 | 0.01 | 5882000.00 | cop[tikv] | | eq(test.t.a, 1), eq(test.t.b, 1) |
+| └─TableFullScan_9 | 10000.00 | 4884000.00 | cop[tikv] | table:t | keep order:false, stats:pseudo |
+```
+
+You can even add predicates to filter cached plans you want:
+
+```sql
+select * from information_schema.tidb_plan_cache where sql_digest=?;
+select * from information_schema.tidb_plan_cache where sql_text like ?;
+select * from information_schema.tidb_plan_cache where executions > 100;
+```
+
+# When to Recompile
+
+Sometimes the optimizer has to recompile a cached plan due to environment changes, for example, if the user changes the table schema, the optimizer has to recompile related queries:
+
+```sql
+create table t (a int, b int, key(a));
+prepare st from "select a from t where a=?";
+set @a=1;
+execute st using @a;
+execute st using @a;
+select @@last_plan_from_cache; -- return 1 since it can hit the last plan
+
+alter table t drop index a; -- drop an index on this table
+execute st using @a;
+select @@last_plan_from_cache; -- return 0 since the DDL change triggers plan recompile
+```
+
+Below list all cases that the optimizer has to recompile the plan:
+
+- The current DB name, user name, timezone, charset, collation are changed.
+- Values of these variables or config are changed: `tidb_restricted_read_only`, `sql_mode`, `tidb_super_read_only`, `foreign_key_checks`, `tidb_enable_shared_lock_promotion`, `pessimistic-auto-commit`.
+- Table schema is changed.
+- Table statistics is changed and `tidb_plan_cache_invalidation_on_fresh_stats` is true.
+- Numbers in Limit-Clause like `limit ?` is changed and `tidb_enable_plan_cache_for_param_limit` is true.
+- Whether this query is in a transaction or not.
+- A new SQL binding is created for this SQL.
+
+# Limitations
+
+## Plan Cache
+
+In the current version of TiDB, if the statement meets any of the following conditions, the query or the plan is not cached:
+
+- The query contains SQL statements other than `SELECT`, `UPDATE`, `INSERT`, `DELETE`, `Union`, `Intersect`, and `Except`.
+- The query accesses temporary tables, or a table that contains generated columns, or uses static mode (that is, [`tidb_partition_prune_mode`](/system-variables.md#tidb_partition_prune_mode-new-in-v51) is set to `static`) to access partitioning tables.
+- The query contains non-correlated sub-queries, such as `SELECT * FROM t1 WHERE t1.a > (SELECT 1 FROM t2 WHERE t2.b < 1)`.
+- The query contains correlated sub-queries with `PhysicalApply` operators in the execution plan, such as `SELECT * FROM t1 WHERE t1.a > (SELECT a FROM t2 WHERE t1.b > t2.b)`.
+- The query contains the `ignore_plan_cache` or `set_var` hint, such as `SELECT /*+ ignore_plan_cache() */ * FROM t` or `SELECT /*+ set_var(max_execution_time=1) */ * FROM t`.
+- The query contains variables other than `?` (including system variables or user-defined variables), such as `select * from t where a>? and b>@x`.
+- The query contains the functions that cannot be cached: `database()`, `current_user`, `current_role`, `user`, `connection_id`, `last_insert_id`, `row_count`, `version`, and `like`.
+- The query uses a variable as the `LIMIT` parameter (such as `LIMIT ?` and `LIMIT 10, ?`) and the variable value is greater than 10000.
+- The query contains `?` after `Order By`, such as `Order By ?`. Such queries sort data based on the column specified by `?`. If the queries targeting different columns use the same execution plan, the results will be wrong. Therefore, such queries are not cached. However, if the query is a common one, such as `Order By a+?`, it is cached.
+- The query contains `?` after `Group By`, such as `Group By?`. Such queries group data based on the column specified by `?`. If the queries targeting different columns use the same execution plan, the results will be wrong. Therefore, such queries are not cached. However, if the query is a common one, such as `Group By a+?`, it is cached.
+- The query contains `?` in the definition of the `Window Frame` window function, such as `(partition by year order by sale rows ? preceding)`. If `?` appears elsewhere in the window function, the query is cached.
+- The query contains parameters for comparing `int` and `string`, such as `c_int >= ?` or `c_int in (?, ?)`, in which `?` indicates the string type, such as `set @x='123'`. To ensure that the query result is compatible with MySQL, parameters need to be adjusted in each query, so such queries are not cached.
+- The plan attempts to access `TiFlash`.
+- In most cases, the plan that contains `TableDual` is not cached, unless the current `Prepare` statement does not have parameters.
+- The query accesses TiDB system views, such as `information_schema.columns`. It is not recommended to use `Prepare` and `Execute` statements to access system views.
+- TiDB has a limitation on the number of `?` in a query. If a query contains more than 65535 `?`, an error `Prepared statement contains too many placeholders` is reported.
+
+## Non-Prepared Plan Cache
+
+Non-Prepared Plan Cache has all limitations that Prepared Plan Cache has, and besides that, Non-Prepared Plan Cache only supports simple TP queries.
+
+Below are its limitations:
+
+- Queries or plans that are not supported by the Prepared plan cache are also not supported by the non-prepared plan cache.
+- Queries or plans that are not supported by the [Prepared plan cache](/sql-plan-cache.md) are also not supported by the non-prepared plan cache.
+- Queries that contain complex operators such as `Window` or `Having` are not supported.
+- Queries that contain three or more `Join` tables or subqueries are not supported.
+- Queries that contain numbers or expressions directly after `ORDER BY` or `GROUP BY` are not supported, such as `ORDER BY 1` and `GROUP BY a+1`. Only `ORDER BY column_name` and `GROUP BY column_name` are supported.
+- 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 200 parameters after parameterization are not supported by default, such as `SELECT * FROM t WHERE a in (1, 2, 3, ... 201)`. Starting from v7.3.0, you can modify this limit by setting the [`44823`](/optimizer-fix-controls.md#44823-new-in-v730) fix in the [`tidb_opt_fix_control`](/system-variables.md#tidb_opt_fix_control-new-in-v653-and-v710) system variable.
+- Queries that access 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 or bindings are not supported.
+- DML statements or `SELECT` statements with the `FOR UPDATE` clause are not supported by default. To remove this restriction, you can execute `SET tidb_enable_non_prepared_plan_cache_for_dml = ON`.
+
+After you enable this feature, the optimizer quickly evaluates the query. If it does not meet the support conditions for non-prepared plan cache, the query falls back to the regular optimization process.
+
+# Others
+
+## Ignore the `COM_STMT_CLOSE` command and the `DEALLOCATE PREPARE` statement
+
+To reduce the syntax parsing cost of SQL statements, it is recommended that you run `prepare stmt` once, then `execute stmt` multiple times before running `deallocate prepare`:
+
+```sql
+MySQL [test]> prepare stmt from '...'; -- Prepare once
+MySQL [test]> execute stmt using ...; -- Execute once
+MySQL [test]> ...
+MySQL [test]> execute stmt using ...; -- Execute multiple times
+MySQL [test]> deallocate prepare stmt; -- Release the prepared statement
+```
+
+In real practice, you may be used to running `deallocate prepare` each time after running `execute stmt`, as shown below:
+
+```sql
+MySQL [test]> prepare stmt from '...'; -- Prepare once
+MySQL [test]> execute stmt using ...;
+MySQL [test]> deallocate prepare stmt; -- Release the prepared statement
+MySQL [test]> prepare stmt from '...'; -- Prepare twice
+MySQL [test]> execute stmt using ...;
+MySQL [test]> deallocate prepare stmt; -- Release the prepared statement
+```
+
+In such practice, the plan obtained by the first executed statement cannot be reused by the second executed statement.
+
+To address the problem, you can set the system variable [`tidb_ignore_prepared_cache_close_stmt`](/system-variables.md#tidb_ignore_prepared_cache_close_stmt-new-in-v600) to `ON` so TiDB ignores commands to close `prepare stmt`:
+
+{{< copyable "sql" >}}
+
+```sql
+mysql> set @@tidb_ignore_prepared_cache_close_stmt=1; -- Enable the variable
+Query OK, 0 rows affected (0.00 sec)
+
+mysql> prepare stmt from 'select * from t'; -- Prepare once
+Query OK, 0 rows affected (0.00 sec)
+
+mysql> execute stmt; -- Execute once
+Empty set (0.00 sec)
+
+mysql> deallocate prepare stmt; -- Release after the first execute
+Query OK, 0 rows affected (0.00 sec)
+
+mysql> prepare stmt from 'select * from t'; -- Prepare twice
+Query OK, 0 rows affected (0.00 sec)
+
+mysql> execute stmt; -- Execute twice
+Empty set (0.00 sec)
+
+mysql> select @@last_plan_from_cache; -- Reuse the last plan
++------------------------+
+| @@last_plan_from_cache |
++------------------------+
+| 1 |
++------------------------+
+1 row in set (0.00 sec)
+```
\ No newline at end of file
diff --git a/sql-prepared-plan-cache.md b/sql-prepared-plan-cache.md
deleted file mode 100644
index 1b85d938d6416..0000000000000
--- a/sql-prepared-plan-cache.md
+++ /dev/null
@@ -1,374 +0,0 @@
----
-title: SQL Prepared Execution Plan Cache
-summary: Learn about SQL Prepared Execution Plan Cache in TiDB.
-aliases: ['/tidb/dev/sql-prepare-plan-cache']
----
-
-# SQL Prepared Execution Plan Cache
-
-TiDB supports execution plan caching for `Prepare` and `Execute` queries. This includes both forms of prepared statements:
-
-- Using the `COM_STMT_PREPARE` and `COM_STMT_EXECUTE` protocol features.
-- Using the SQL statements `PREPARE` and `EXECUTE`.
-
-The TiDB optimizer handles these two types of queries in the same way: when preparing, the parameterized query is parsed into an AST (Abstract Syntax Tree) and cached; in later execution, the execution plan is generated based on the stored AST and specific parameter values.
-
-When the execution plan cache is enabled, in the first execution every `Prepare` statement checks whether the current query can use the execution plan cache, and if the query can use it, then put the generated execution plan into a cache implemented by LRU (Least Recently Used) linked list. In the subsequent `Execute` queries, the execution plan is obtained from the cache and checked for availability. If the check succeeds, the step of generating an execution plan is skipped. Otherwise, the execution plan is regenerated and saved in the cache.
-
-TiDB also supports execution plan caching for some non-`PREPARE` statements, similar to the `Prepare`/`Execute` statements. For more details, refer to [Non-prepared plan cache](/sql-non-prepared-plan-cache.md).
-
-In the current version of TiDB, if a `Prepare` statement meets any of the following conditions, the query or the plan is not cached:
-
-- The query contains SQL statements other than `SELECT`, `UPDATE`, `INSERT`, `DELETE`, `Union`, `Intersect`, and `Except`.
-- The query accesses temporary tables, or a table that contains generated columns, or uses static mode (that is, [`tidb_partition_prune_mode`](/system-variables.md#tidb_partition_prune_mode-new-in-v51) is set to `static`) to access partitioning tables.
-- The query contains non-correlated sub-queries, such as `SELECT * FROM t1 WHERE t1.a > (SELECT 1 FROM t2 WHERE t2.b < 1)`.
-- The query contains correlated sub-queries with `PhysicalApply` operators in the execution plan, such as `SELECT * FROM t1 WHERE t1.a > (SELECT a FROM t2 WHERE t1.b > t2.b)`.
-- The query contains the `ignore_plan_cache` or `set_var` hint, such as `SELECT /*+ ignore_plan_cache() */ * FROM t` or `SELECT /*+ set_var(max_execution_time=1) */ * FROM t`.
-- The query contains variables other than `?` (including system variables or user-defined variables), such as `select * from t where a>? and b>@x`.
-- The query contains the functions that cannot be cached: `database()`, `current_user`, `current_role`, `user`, `connection_id`, `last_insert_id`, `row_count`, `version`, and `like`.
-- The query uses a variable as the `LIMIT` parameter (such as `LIMIT ?` and `LIMIT 10, ?`) and the variable value is greater than 10000.
-- The query contains `?` after `Order By`, such as `Order By ?`. Such queries sort data based on the column specified by `?`. If the queries targeting different columns use the same execution plan, the results will be wrong. Therefore, such queries are not cached. However, if the query is a common one, such as `Order By a+?`, it is cached.
-- The query contains `?` after `Group By`, such as `Group By?`. Such queries group data based on the column specified by `?`. If the queries targeting different columns use the same execution plan, the results will be wrong. Therefore, such queries are not cached. However, if the query is a common one, such as `Group By a+?`, it is cached.
-- The query contains `?` in the definition of the `Window Frame` window function, such as `(partition by year order by sale rows ? preceding)`. If `?` appears elsewhere in the window function, the query is cached.
-- The query contains parameters for comparing `int` and `string`, such as `c_int >= ?` or `c_int in (?, ?)`, in which `?` indicates the string type, such as `set @x='123'`. To ensure that the query result is compatible with MySQL, parameters need to be adjusted in each query, so such queries are not cached.
-- The plan attempts to access `TiFlash`.
-- In most cases, the plan that contains `TableDual` is not cached, unless the current `Prepare` statement does not have parameters.
-- The query accesses TiDB system views, such as `information_schema.columns`. It is not recommended to use `Prepare` and `Execute` statements to access system views.
-
-TiDB has a limitation on the number of `?` in a query. If a query contains more than 65535 `?`, an error `Prepared statement contains too many placeholders` is reported.
-
-The LRU linked list is designed as a session-level cache because `Prepare`/`Execute` cannot be executed across sessions. Each element of the LRU list is a key-value pair. The value is the execution plan, and the key is composed of the following parts:
-
-- The name of the database where `Execute` is executed
-- The identifier of the `Prepare` statement, that is, the name after the `PREPARE` keyword
-- The current schema version, which is updated after every successfully executed DDL statement
-- The SQL mode when executing `Execute`
-- The current time zone, which is the value of the `time_zone` system variable
-- The value of the `sql_select_limit` system variable
-
-Any change in the preceding information (for example, switching databases, renaming `Prepare` statement, executing DDL statements, or modifying the value of SQL mode/`time_zone`), or the LRU cache elimination mechanism causes the execution plan cache miss when executing.
-
-After the execution plan cache is obtained from the cache, TiDB first checks whether the execution plan is still valid. If the current `Execute` statement is executed in an explicit transaction, and the referenced table is modified in the transaction pre-order statement, the cached execution plan accessing this table does not contain the `UnionScan` operator, then it cannot be executed.
-
-After the validation test is passed, the scan range of the execution plan is adjusted according to the current parameter values, and then used to perform data querying.
-
-There are several points worth noting about execution plan caching and query performance:
-
-- No matter an execution plan is cached or not, it is affected by SQL bindings. For execution plans that have not been cached (the first `Execute`), these plans are affected by existing SQL bindings. For execution plans that have been cached, if new SQL Bindings are created, these plans become invalid.
-- Cached plans are not affected by changes in statistics, optimization rules, and blocklist pushdown by expressions.
-- Considering that the parameters of `Execute` are different, the execution plan cache prohibits some aggressive query optimization methods that are closely related to specific parameter values to ensure adaptability. This causes that the query plan may not be optimal for certain parameter values. For example, the filter condition of the query is `where a > ? And a < ?`, the parameters of the first `Execute` statement are `2` and `1` respectively. Considering that these two parameters maybe be `1` and `2` in the next execution time, the optimizer does not generate the optimal `TableDual` execution plan that is specific to current parameter values;
-- If cache invalidation and elimination are not considered, an execution plan cache is applied to various parameter values, which in theory also results in non-optimal execution plans for certain values. For example, if the filter condition is `where a < ?` and the parameter value used for the first execution is `1`, then the optimizer generates the optimal `IndexScan` execution plan and puts it into the cache. In the subsequent executions, if the value becomes `10000`, the `TableScan` plan might be the better one. But due to the execution plan cache, the previously generated `IndexScan` is used for execution. Therefore, the execution plan cache is more suitable for application scenarios where the query is simple (the ratio of compilation is high) and the execution plan is relatively fixed.
-
-Starting from v6.1.0, the execution plan cache is enabled by default. You can control prepared plan cache via the system variable [`tidb_enable_prepared_plan_cache`](/system-variables.md#tidb_enable_prepared_plan_cache-new-in-v610).
-
-> **Note:**
->
-> The [`tidb_enable_prepared_plan_cache`](/system-variables.md#tidb_enable_prepared_plan_cache-new-in-v610) system variable controls the execution plan cache only for `Prepare`/`Execute` queries, not for normal queries. For the execution plan cache for normal queries, see [SQL Non-Prepared Execution Plan Cache](/sql-non-prepared-plan-cache.md).
-
-After the execution plan cache feature is enabled, you can use the session-level system variable [`last_plan_from_cache`](/system-variables.md#last_plan_from_cache-new-in-v40) to see whether the previous `Execute` statement used the cached execution plan, for example:
-
-{{< copyable "sql" >}}
-
-```sql
-MySQL [test]> create table t(a int);
-Query OK, 0 rows affected (0.00 sec)
-MySQL [test]> prepare stmt from 'select * from t where a = ?';
-Query OK, 0 rows affected (0.00 sec)
-MySQL [test]> set @a = 1;
-Query OK, 0 rows affected (0.00 sec)
-
--- The first execution generates an execution plan and saves it in the cache.
-MySQL [test]> execute stmt using @a;
-Empty set (0.00 sec)
-MySQL [test]> select @@last_plan_from_cache;
-+------------------------+
-| @@last_plan_from_cache |
-+------------------------+
-| 0 |
-+------------------------+
-1 row in set (0.00 sec)
-
--- The second execution hits the cache.
-MySQL [test]> execute stmt using @a;
-Empty set (0.00 sec)
-MySQL [test]> select @@last_plan_from_cache;
-+------------------------+
-| @@last_plan_from_cache |
-+------------------------+
-| 1 |
-+------------------------+
-1 row in set (0.00 sec)
-```
-
-If you find that a certain set of `Prepare`/`Execute` has unexpected behavior due to the execution plan cache, you can use the `ignore_plan_cache()` SQL hint to skip using the execution plan cache for the current statement. Still, use the preceding statement as an example:
-
-{{< copyable "sql" >}}
-
-```sql
-MySQL [test]> prepare stmt from 'select /*+ ignore_plan_cache() */ * from t where a = ?';
-Query OK, 0 rows affected (0.00 sec)
-MySQL [test]> set @a = 1;
-Query OK, 0 rows affected (0.00 sec)
-MySQL [test]> execute stmt using @a;
-Empty set (0.00 sec)
-MySQL [test]> select @@last_plan_from_cache;
-+------------------------+
-| @@last_plan_from_cache |
-+------------------------+
-| 0 |
-+------------------------+
-1 row in set (0.00 sec)
-MySQL [test]> execute stmt using @a;
-Empty set (0.00 sec)
-MySQL [test]> select @@last_plan_from_cache;
-+------------------------+
-| @@last_plan_from_cache |
-+------------------------+
-| 0 |
-+------------------------+
-1 row in set (0.00 sec)
-```
-
-## Diagnostics of Prepared Plan Cache
-
-### Use `SHOW WARNINGS` to diagnose
-
-Some queries or plans cannot be cached. You can use the `SHOW WARNINGS` statement to check whether the query or plan is cached. If it is not cached, you can check the reason for the failure in the result. For example:
-
-```sql
-mysql> PREPARE st FROM 'SELECT * FROM t WHERE a > (SELECT MAX(a) FROM t)'; -- The query contains a subquery and cannot be cached.
-
-Query OK, 0 rows affected, 1 warning (0.01 sec)
-
-mysql> SHOW WARNINGS; -- Checks the reason why the query plan cannot be cached.
-
-+---------+------+-----------------------------------------------+
-| Level | Code | Message |
-+---------+------+-----------------------------------------------+
-| Warning | 1105 | skip plan-cache: sub-queries are un-cacheable |
-+---------+------+-----------------------------------------------+
-1 row in set (0.00 sec)
-
-mysql> prepare st from 'select * from t where a';
-
-Query OK, 0 rows affected (0.00 sec)
-
-mysql> set @a='1';
-
-Query OK, 0 rows affected (0.00 sec)
-
-mysql> execute st using @a; -- The optimization converts a non-INT type to an INT type, and the execution plan might change with the change of the parameter, so TiDB does not cache the plan.
-
-Empty set, 1 warning (0.01 sec)
-
-mysql> SHOW WARNINGS;
-
-+---------+------+----------------------------------------------+
-| Level | Code | Message |
-+---------+------+----------------------------------------------+
-| Warning | 1105 | skip plan-cache: '1' may be converted to INT |
-+---------+------+----------------------------------------------+
-1 row in set (0.00 sec)
-```
-
-### Use `Statements Summary` to diagnose
-
-The `Statements Summary` table contains two fields, `plan_cache_unqualified` and `plan_cache_unqualified_last_reason`, which respectively indicate the number of times and the reason why the corresponding query is unable to use the plan cache. You can use these two fields for diagnostic purposes:
-
-```sql
-mysql> SELECT digest_text, plan_cache_unqualified, plan_cache_unqualified_last_reason FROM information_schema.statements_summary WHERE plan_cache_unqualified > 0 ORDER BY plan_cache_unqualified DESC
-LIMIT 10;
-
-+---------------------------------+------------------------+----------------------------------------+
-| digest_text | plan_cache_unqualified | plan_cache_unqualified_last_reason |
-+---------------------------------+------------------------+----------------------------------------+
-| select * from `t` where `a` < ? | 10 | '1' may be converted to INT |
-| select * from `t` order by ? | 4 | query has 'order by ?' is un-cacheable |
-| select database ( ) from `t` | 2 | query has 'database()' is un-cacheable |
-...
-+---------------------------------+------------------------+----------------------------------------+
-10 row in set (0.01 sec)
-```
-
-## Memory management of Prepared Plan Cache
-
-
-
-Using Prepared Plan Cache incurs memory overhead. To view the total memory consumption by the cached execution plans of all sessions in each TiDB instance, you can use the [**Plan Cache Memory Usage** monitoring panel](/grafana-tidb-dashboard.md) in Grafana.
-
-> **Note:**
->
-> Because of the memory reclaim mechanism of Golang and some uncounted memory structures, the memory displayed in Grafana is not equal to the actual heap memory usage. It is tested that there is a deviation of about ±20% between the memory displayed in Grafana and the actual heap memory usage.
-
-To view the total number of execution plans cached in each TiDB instance, you can use the [**Plan Cache Plan Num** panel](/grafana-tidb-dashboard.md) in Grafana.
-
-The following is an example of the **Plan Cache Memory Usage** and **Plan Cache Plan Num** panels in Grafana:
-
-![grafana_panels](/media/planCache-memoryUsage-planNum-panels.png)
-
-Starting from v7.1.0, you can control the maximum number of plans that can be cached in each session by configuring the system variable [`tidb_session_plan_cache_size`](/system-variables.md#tidb_session_plan_cache_size-new-in-v710). For different environments, the recommended value is as follows and you can adjust it according to the monitoring panels:
-
-
-
-
-
-Using Prepared Plan Cache has some memory overhead. In internal tests, each cached plan consumes an average of 100 KiB of memory. Because Plan Cache is currently at the `SESSION` level, the total memory consumption is approximately `the number of sessions * the average number of cached plans in a session * 100 KiB`.
-
-For example, the current TiDB instance has 50 sessions in concurrency and each session has approximately 100 cached plans. The total memory consumption is approximately `50 * 100 * 100 KiB` = `512 MB`.
-
-You can control the maximum number of plans that can be cached in each session by configuring the system variable [`tidb_session_plan_cache_size`](/system-variables.md#tidb_session_plan_cache_size-new-in-v710). For different environments, the recommended value is as follows:
-
-
-
-- When the memory threshold of the TiDB server instance is <= 64 GiB, set `tidb_session_plan_cache_size` to `50`.
-- When the memory threshold of the TiDB server instance is > 64 GiB, set `tidb_session_plan_cache_size` to `100`.
-
-Starting from v7.1.0, you can control the maximum size of a plan that can be cached using the system variable [`tidb_plan_cache_max_plan_size`](/system-variables.md#tidb_plan_cache_max_plan_size-new-in-v710). The default value is 2 MB. If the size of a plan exceeds this value, the plan will not be cached.
-
-When the unused memory of the TiDB server is less than a certain threshold, the memory protection mechanism of plan cache is triggered, through which some cached plans will be evicted.
-
-You can control the threshold by configuring the system variable `tidb_prepared_plan_cache_memory_guard_ratio`. The threshold is 0.1 by default, which means when the unused memory of the TiDB server is less than 10% of the total memory (90% of the memory is used), the memory protection mechanism is triggered.
-
-
-
-Due to memory limit, plan cache might be missed sometimes. You can check the status by viewing the [`Plan Cache Miss OPS` metric](/grafana-tidb-dashboard.md) in the Grafana dashboard.
-
-
-
-
-
-Due to memory limit, plan cache might be missed sometimes.
-
-
-
-## Clear execution plan cache
-
-You can clear execution plan cache by executing the `ADMIN FLUSH [SESSION | INSTANCE] PLAN_CACHE` statement.
-
-In this statement, `[SESSION | INSTANCE]` specifies whether the plan cache is cleared for the current session or the whole TiDB instance. If the scope is not specified, the preceding statement applies to the `SESSION` cache by default.
-
-The following is an example of clearing the `SESSION` execution plan cache:
-
-{{< copyable "sql" >}}
-
-```sql
-MySQL [test]> create table t (a int);
-Query OK, 0 rows affected (0.00 sec)
-
-MySQL [test]> prepare stmt from 'select * from t';
-Query OK, 0 rows affected (0.00 sec)
-
-MySQL [test]> execute stmt;
-Empty set (0.00 sec)
-
-MySQL [test]> execute stmt;
-Empty set (0.00 sec)
-
-MySQL [test]> select @@last_plan_from_cache; -- Select the cached plan
-+------------------------+
-| @@last_plan_from_cache |
-+------------------------+
-| 1 |
-+------------------------+
-1 row in set (0.00 sec)
-
-MySQL [test]> admin flush session plan_cache; -- Clear the cached plan of the current session
-Query OK, 0 rows affected (0.00 sec)
-
-MySQL [test]> execute stmt;
-Empty set (0.00 sec)
-
-MySQL [test]> select @@last_plan_from_cache; -- The cached plan cannot be selected again, because it has been cleared
-+------------------------+
-| @@last_plan_from_cache |
-+------------------------+
-| 0 |
-+------------------------+
-1 row in set (0.00 sec)
-```
-
-Currently, TiDB does not support clearing `GLOBAL` execution plan cache. That means you cannot clear the cached plan of the whole TiDB cluster. The following error is reported if you try to clear the `GLOBAL` execution plan cache:
-
-{{< copyable "sql" >}}
-
-```sql
-MySQL [test]> admin flush global plan_cache;
-ERROR 1105 (HY000): Do not support the 'admin flush global scope.'
-```
-
-## Ignore the `COM_STMT_CLOSE` command and the `DEALLOCATE PREPARE` statement
-
-To reduce the syntax parsing cost of SQL statements, it is recommended that you run `prepare stmt` once, then `execute stmt` multiple times before running `deallocate prepare`:
-
-{{< copyable "sql" >}}
-
-```sql
-MySQL [test]> prepare stmt from '...'; -- Prepare once
-MySQL [test]> execute stmt using ...; -- Execute once
-MySQL [test]> ...
-MySQL [test]> execute stmt using ...; -- Execute multiple times
-MySQL [test]> deallocate prepare stmt; -- Release the prepared statement
-```
-
-In real practice, you may be used to running `deallocate prepare` each time after running `execute stmt`, as shown below:
-
-{{< copyable "sql" >}}
-
-```sql
-MySQL [test]> prepare stmt from '...'; -- Prepare once
-MySQL [test]> execute stmt using ...;
-MySQL [test]> deallocate prepare stmt; -- Release the prepared statement
-MySQL [test]> prepare stmt from '...'; -- Prepare twice
-MySQL [test]> execute stmt using ...;
-MySQL [test]> deallocate prepare stmt; -- Release the prepared statement
-```
-
-In such practice, the plan obtained by the first executed statement cannot be reused by the second executed statement.
-
-To address the problem, you can set the system variable [`tidb_ignore_prepared_cache_close_stmt`](/system-variables.md#tidb_ignore_prepared_cache_close_stmt-new-in-v600) to `ON` so TiDB ignores commands to close `prepare stmt`:
-
-{{< copyable "sql" >}}
-
-```sql
-mysql> set @@tidb_ignore_prepared_cache_close_stmt=1; -- Enable the variable
-Query OK, 0 rows affected (0.00 sec)
-
-mysql> prepare stmt from 'select * from t'; -- Prepare once
-Query OK, 0 rows affected (0.00 sec)
-
-mysql> execute stmt; -- Execute once
-Empty set (0.00 sec)
-
-mysql> deallocate prepare stmt; -- Release after the first execute
-Query OK, 0 rows affected (0.00 sec)
-
-mysql> prepare stmt from 'select * from t'; -- Prepare twice
-Query OK, 0 rows affected (0.00 sec)
-
-mysql> execute stmt; -- Execute twice
-Empty set (0.00 sec)
-
-mysql> select @@last_plan_from_cache; -- Reuse the last plan
-+------------------------+
-| @@last_plan_from_cache |
-+------------------------+
-| 1 |
-+------------------------+
-1 row in set (0.00 sec)
-```
-
-### Monitoring
-
-
-
-In [the Grafana dashboard](/grafana-tidb-dashboard.md) on the TiDB page in the **Executor** section, there are the "Queries Using Plan Cache OPS" and "Plan Cache Miss OPS" graphs. These graphs can be used to check if both TiDB and the application are configured correctly to allow the SQL Plan Cache to work correctly. The **Server** section on the same page provides the "Prepared Statement Count" graph. This graph shows a non-zero value if the application uses prepared statements, which is required for the SQL Plan Cache to function correctly.
-
-![`sql_plan_cache`](/media/performance/sql_plan_cache.png)
-
-
-
-
-
-On the [**Monitoring**](/tidb-cloud/built-in-monitoring.md) page of the [TiDB Cloud console](https://tidbcloud.com/), you can check the `Queries Using Plan Cache OPS` metric to get the number of queries using or missing plan cache per second in all TiDB instances.
-
-
diff --git a/sql-statements/sql-statement-explain.md b/sql-statements/sql-statement-explain.md
index 2c2f4ef77b9d3..4cc45107d975d 100644
--- a/sql-statements/sql-statement-explain.md
+++ b/sql-statements/sql-statement-explain.md
@@ -201,7 +201,7 @@ To specify the format of the `EXPLAIN` output, you can use the `FORMAT = xxx` sy
| `row` | The `EXPLAIN` statement outputs results in a tabular format. See [Understand the Query Execution Plan](/explain-overview.md) for more information. |
| `tidb_json` | The `EXPLAIN` statement outputs execution plans in JSON and stores the operator information in a JSON array. |
| `verbose` | The `EXPLAIN` statement outputs results in the `row` format, with an additional `estCost` column for the estimated cost of the query in the results. For more information about how to use this format, see [SQL Plan Management](/sql-plan-management.md). |
-| `plan_cache` | The `EXPLAIN` statement outputs results in the `row` format, with the [Plan Cache](/sql-non-prepared-plan-cache.md#diagnostics) information as a warning. |
+| `plan_cache` | The `EXPLAIN` statement outputs results in the `row` format, with the [Plan Cache](/sql-plan-cache.md#management-and-diagnosis-of-plan-cache) information as a warning. |
diff --git a/system-variable-reference.md b/system-variable-reference.md
index 7f0643abb192e..4c3cb50df52c0 100644
--- a/system-variable-reference.md
+++ b/system-variable-reference.md
@@ -449,7 +449,7 @@ Referenced in:
- [Connect to TiDB with mysql2](/develop/dev-guide-sample-application-ruby-mysql2.md)
- [Information Functions](/functions-and-operators/information-functions.md)
- [SHOW BUILTINS](/sql-statements/sql-statement-show-builtins.md)
-- [SQL Prepared Execution Plan Cache](/sql-prepared-plan-cache.md)
+- [SQL Plan Cache](/sql-plan-cache.md)
- [System Variables](/system-variables.md#last_insert_id)
- [TiDB 7.2.0 Release Notes](/releases/release-7.2.0.md)
- [TiDB 3.1 RC Release Notes](/releases/release-3.1.0-rc.md)
@@ -469,8 +469,7 @@ Referenced in:
Referenced in:
- [Index Selection](/choose-index.md)
-- [SQL Non-Prepared Execution Plan Cache](/sql-non-prepared-plan-cache.md)
-- [SQL Prepared Execution Plan Cache](/sql-prepared-plan-cache.md)
+- [SQL Plan Cache](/sql-plan-cache.md)
- [System Variables](/system-variables.md#last_plan_from_cache-new-in-v40)
- [TiDB 4.0.2 Release Notes](/releases/release-4.0.2.md)
@@ -524,7 +523,7 @@ Referenced in:
- [Connection Pools and Connection Parameters](/develop/dev-guide-connection-parameters.md)
- [Optimizer Hints](/optimizer-hints.md)
- [SQL Plan Management (SPM)](/sql-plan-management.md)
-- [SQL Prepared Execution Plan Cache](/sql-prepared-plan-cache.md)
+- [SQL Plan Cache](/sql-plan-cache.md)
- [System Variables](/system-variables.md#max_execution_time)
- [Timeouts in TiDB](/develop/dev-guide-timeouts-in-tidb.md)
- [Troubleshoot TiDB OOM Issues](/troubleshoot-tidb-oom.md)
@@ -701,7 +700,7 @@ Referenced in:
Referenced in:
-- [SQL Prepared Execution Plan Cache](/sql-prepared-plan-cache.md)
+- [SQL Plan Cache](/sql-plan-cache.md)
- [System Variables](/system-variables.md#sql_select_limit-new-in-v402)
- [TiDB 4.0.2 Release Notes](/releases/release-4.0.2.md)
@@ -1709,7 +1708,7 @@ Referenced in:
Referenced in:
-- [SQL Non-Prepared Execution Plan Cache](/sql-non-prepared-plan-cache.md)
+- [SQL Non-Plan Cache](/sql-plan-cache.md)
- [System Variables](/system-variables.md#tidb_enable_non_prepared_plan_cache)
- [tidb-performance-tuning-config](/tidb-performance-tuning-config.md)
- [TiDB 7.4.0 Release Notes](/releases/release-7.4.0.md)
@@ -1722,7 +1721,7 @@ Referenced in:
Referenced in:
-- [SQL Non-Prepared Execution Plan Cache](/sql-non-prepared-plan-cache.md)
+- [SQL Non-Plan Cache](/sql-plan-cache.md)
- [System Variables](/system-variables.md#tidb_enable_non_prepared_plan_cache_for_dml-new-in-v710)
- [TiDB 7.1.0 Release Notes](/releases/release-7.1.0.md)
@@ -1849,7 +1848,7 @@ Referenced in:
Referenced in:
- [How to Test TiDB Using Sysbench](/benchmark/benchmark-tidb-using-sysbench.md)
-- [SQL Prepared Execution Plan Cache](/sql-prepared-plan-cache.md)
+- [SQL Plan Cache](/sql-plan-cache.md)
- [System Variables](/system-variables.md#tidb_enable_prepared_plan_cache-new-in-v610)
- [TiDB Cloud Release Notes in 2022](https://docs.pingcap.com/tidbcloud/release-notes-2022)
- [TiDB Dashboard FAQs](/dashboard/dashboard-faq.md)
@@ -2357,7 +2356,7 @@ Referenced in:
- [Performance Analysis and Tuning](/performance-tuning-methods.md)
- [Performance Tuning Practices for OLTP Scenarios](/performance-tuning-practices.md)
-- [SQL Prepared Execution Plan Cache](/sql-prepared-plan-cache.md)
+- [SQL Plan Cache](/sql-plan-cache.md)
- [System Variables](/system-variables.md#tidb_ignore_prepared_cache_close_stmt-new-in-v600)
- [tidb-performance-tuning-config](/tidb-performance-tuning-config.md)
- [TiDB 6.0.0 Release Notes](/releases/release-6.0.0-dmr.md)
@@ -2957,7 +2956,7 @@ Referenced in:
- [Control Execution Plan](/control-execution-plan.md)
- [Optimizer Fix Controls](/optimizer-fix-controls.md)
-- [SQL Non-Prepared Execution Plan Cache](/sql-non-prepared-plan-cache.md)
+- [SQL Non-Plan Cache](/sql-plan-cache.md)
- [System Variables](/system-variables.md#tidb_opt_fix_control-new-in-v653-and-v710)
- [tidb-performance-tuning-config](/tidb-performance-tuning-config.md)
- [TiDB 7.2.0 Release Notes](/releases/release-7.2.0.md)
@@ -3135,7 +3134,7 @@ Referenced in:
Referenced in:
- [Partitioning](/partitioned-table.md)
-- [SQL Prepared Execution Plan Cache](/sql-prepared-plan-cache.md)
+- [SQL Plan Cache](/sql-plan-cache.md)
- [System Variables](/system-variables.md#tidb_partition_prune_mode-new-in-v51)
- [TiFlash Upgrade Guide](/tiflash-upgrade-guide.md)
- [Use TiFlash MPP Mode](/tiflash/use-tiflash-mpp-mode.md)
@@ -3181,8 +3180,8 @@ Referenced in:
Referenced in:
-- [SQL Non-Prepared Execution Plan Cache](/sql-non-prepared-plan-cache.md)
-- [SQL Prepared Execution Plan Cache](/sql-prepared-plan-cache.md)
+- [SQL Non-Plan Cache](/sql-plan-cache.md)
+- [SQL Plan Cache](/sql-plan-cache.md)
- [System Variables](/system-variables.md#tidb_plan_cache_max_plan_size-new-in-v710)
- [TiDB 7.1.0 Release Notes](/releases/release-7.1.0.md)
@@ -3214,7 +3213,7 @@ Referenced in:
Referenced in:
-- [SQL Prepared Execution Plan Cache](/sql-prepared-plan-cache.md)
+- [SQL Plan Cache](/sql-plan-cache.md)
- [System Variables](/system-variables.md#tidb_prepared_plan_cache_memory_guard_ratio-new-in-v610)
- [TiDB 6.1.0 Release Notes](/releases/release-6.1.0.md)
@@ -3517,8 +3516,8 @@ Referenced in:
Referenced in:
-- [SQL Non-Prepared Execution Plan Cache](/sql-non-prepared-plan-cache.md)
-- [SQL Prepared Execution Plan Cache](/sql-prepared-plan-cache.md)
+- [SQL Non-Plan Cache](/sql-plan-cache.md)
+- [SQL Plan Cache](/sql-plan-cache.md)
- [System Variables](/system-variables.md#tidb_session_plan_cache_size-new-in-v710)
- [TiDB Cloud Sysbench Performance Test Report for TiDB v8.1.0](https://docs.pingcap.com/tidbcloud/v8.1-performance-benchmarking-with-sysbench)
- [TiDB 7.4.0 Release Notes](/releases/release-7.4.0.md)
@@ -4105,7 +4104,7 @@ Referenced in:
- [Date and Time Types](/data-type-date-and-time.md)
- [SHOW [GLOBAL|SESSION] VARIABLES](/sql-statements/sql-statement-show-variables.md)
-- [SQL Prepared Execution Plan Cache](/sql-prepared-plan-cache.md)
+- [SQL Plan Cache](/sql-plan-cache.md)
- [System Variables](/system-variables.md#time_zone)
- [Time Zone Support](/configure-time-zone.md)
- [TiDB 6.0.0 Release Notes](/releases/release-6.0.0-dmr.md)
diff --git a/system-variables.md b/system-variables.md
index 1ac19b609ce1a..f99f4ccdf30cd 100644
--- a/system-variables.md
+++ b/system-variables.md
@@ -2198,7 +2198,7 @@ mysql> SELECT job_info FROM mysql.analyze_jobs ORDER BY end_time DESC LIMIT 1;
- Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): Yes
- Type: Boolean
- Default value: `OFF`
-- This variable controls whether to enable the [Non-prepared plan cache](/sql-non-prepared-plan-cache.md) feature.
+- This variable controls whether to enable the [Non-prepared plan cache](/sql-plan-cache.md) feature.
- Enabling this feature might incur additional memory and CPU overhead and might not be suitable for all situations. Please determine whether to enable this feature according to your actual scenario.
### tidb_enable_non_prepared_plan_cache_for_dml New in v7.1.0
@@ -2212,7 +2212,7 @@ mysql> SELECT job_info FROM mysql.analyze_jobs ORDER BY end_time DESC LIMIT 1;
- Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): No
- Type: Boolean
- Default value: `OFF`.
-- This variable controls whether to enable the [Non-prepared plan cache](/sql-non-prepared-plan-cache.md) feature for DML statements.
+- This variable controls whether to enable the [Non-prepared plan cache](/sql-plan-cache.md) feature for DML statements.
### tidb_enable_gogc_tuner New in v6.4.0
@@ -2425,7 +2425,7 @@ mysql> SELECT job_info FROM mysql.analyze_jobs ORDER BY end_time DESC LIMIT 1;
- Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): No
- Type: Boolean
- Default value: `OFF`
-- This variable controls whether to enable the Instance Plan Cache feature. This feature implements instance-level execution plan cache, which allows all sessions within the same TiDB instance to share the execution plan cache, thereby improving memory utilization. Before enabling Instance Plan Cache, it is recommended to disable session-level [Prepared execution plan cache](/sql-prepared-plan-cache.md) and [Non-prepared execution plan cache](/sql-non-prepared-plan-cache.md).
+- This variable controls whether to enable the Instance Plan Cache feature. This feature implements instance-level execution plan cache, which allows all sessions within the same TiDB instance to share the execution plan cache, thereby improving memory utilization. Before enabling Instance Plan Cache, it is recommended to disable session-level [Prepared execution plan cache](/sql-plan-cache.md) and [Non-prepared execution plan cache](/sql-plan-cache.md).
### tidb_enable_ordered_result_mode
@@ -2555,7 +2555,7 @@ mysql> SELECT job_info FROM mysql.analyze_jobs ORDER BY end_time DESC LIMIT 1;
- Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): Yes
- Type: Boolean
- Default value: `ON`
-- Determines whether to enable [Prepared Plan Cache](/sql-prepared-plan-cache.md). When it is enabled, the execution plans of `Prepare` and `Execute` are cached so that the subsequent executions skip optimizing the execution plans, which brings performance improvement.
+- Determines whether to enable [Prepared Plan Cache](/sql-plan-cache.md). When it is enabled, the execution plans of `Prepare` and `Execute` are cached so that the subsequent executions skip optimizing the execution plans, which brings performance improvement.
- This setting was previously a `tidb.toml` option (`prepared-plan-cache.enabled`), but changed to a system variable starting from TiDB v6.1.0.
### tidb_enable_prepared_plan_cache_memory_monitor New in v6.4.0
@@ -2564,7 +2564,7 @@ mysql> SELECT job_info FROM mysql.analyze_jobs ORDER BY end_time DESC LIMIT 1;
- Persists to cluster: Yes
- Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): No
- Default value: `ON`
-- This variable controls whether to count the memory consumed by the execution plans cached in the Prepared Plan Cache. For details, see [Memory management of Prepared Plan Cache](/sql-prepared-plan-cache.md#memory-management-of-prepared-plan-cache).
+- This variable controls whether to count the memory consumed by the execution plans cached in the Prepared Plan Cache. For details, see [Memory management of Prepared Plan Cache](/sql-plan-cache.md#memory-management-of-prepared-plan-cache).
### tidb_enable_pseudo_for_outdated_stats New in v5.3.0
@@ -3162,7 +3162,7 @@ For a system upgraded to v5.0 from an earlier version, if you have not modified
- Type: Integer
- Default value: `100`
- Range: `[1, 100000]`
-- This variable controls the maximum number of execution plans that can be cached by [Non-prepared plan cache](/sql-non-prepared-plan-cache.md).
+- This variable controls the maximum number of execution plans that can be cached by [Non-prepared plan cache](/sql-plan-cache.md).
### tidb_pre_split_regions New in v8.4.0
@@ -3344,7 +3344,7 @@ For a system upgraded to v5.0 from an earlier version, if you have not modified
- Type: Boolean
- Default value: `OFF`
- This variable is used to set whether to ignore the commands for closing prepared statement cache.
-- When this variable is set to `ON`, the `COM_STMT_CLOSE` command of the Binary protocol and the [`DEALLOCATE PREPARE`](/sql-statements/sql-statement-deallocate.md) statement of the text protocol are ignored. For details, see [Ignore the `COM_STMT_CLOSE` command and the `DEALLOCATE PREPARE` statement](/sql-prepared-plan-cache.md#ignore-the-com_stmt_close-command-and-the-deallocate-prepare-statement).
+- When this variable is set to `ON`, the `COM_STMT_CLOSE` command of the Binary protocol and the [`DEALLOCATE PREPARE`](/sql-statements/sql-statement-deallocate.md) statement of the text protocol are ignored. For details, see [Ignore the `COM_STMT_CLOSE` command and the `DEALLOCATE PREPARE` statement](/sql-plan-cache.md#ignore-the-com_stmt_close-command-and-the-deallocate-prepare-statement).
### tidb_index_join_batch_size
@@ -4932,7 +4932,7 @@ SHOW WARNINGS;
- Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): Yes
- Default value: `2097152` (which is 2 MiB)
- Range: `[0, 9223372036854775807]`, in bytes. The memory format with the units "KiB|MiB|GiB|TiB" is also supported. `0` means no limit.
-- This variable controls the maximum size of a plan that can be cached in prepared or non-prepared plan cache. If the size of a plan exceeds this value, the plan will not be cached. For more details, see [Memory management of prepared plan cache](/sql-prepared-plan-cache.md#memory-management-of-prepared-plan-cache) and [Non-prepared plan cache](/sql-plan-management.md#usage).
+- This variable controls the maximum size of a plan that can be cached in prepared or non-prepared plan cache. If the size of a plan exceeds this value, the plan will not be cached. For more details, see [Memory management of prepared plan cache](/sql-plan-cache.md#memory-management-of-prepared-plan-cache) and [Non-prepared plan cache](/sql-plan-management.md#usage).
### tidb_pprof_sql_cpu New in v4.0
@@ -4965,7 +4965,7 @@ SHOW WARNINGS;
- Type: Float
- Default value: `0.1`
- Range: `[0, 1]`
-- The threshold at which the prepared plan cache triggers a memory protection mechanism. For details, see [Memory management of Prepared Plan Cache](/sql-prepared-plan-cache.md).
+- The threshold at which the prepared plan cache triggers a memory protection mechanism. For details, see [Memory management of Prepared Plan Cache](/sql-plan-cache.md).
- This setting was previously a `tidb.toml` option (`prepared-plan-cache.memory-guard-ratio`), but changed to a system variable starting from TiDB v6.1.0.
### tidb_prepared_plan_cache_size New in v6.1.0
@@ -4980,7 +4980,7 @@ SHOW WARNINGS;
- Type: Integer
- Default value: `100`
- Range: `[1, 100000]`
-- The maximum number of plans that can be cached in a session. For details, see [Memory management of Prepared Plan Cache](/sql-prepared-plan-cache.md).
+- The maximum number of plans that can be cached in a session. For details, see [Memory management of Prepared Plan Cache](/sql-plan-cache.md).
- This setting was previously a `tidb.toml` option (`prepared-plan-cache.capacity`), but changed to a system variable starting from TiDB v6.1.0.
### tidb_projection_concurrency
@@ -5328,7 +5328,7 @@ SHOW WARNINGS;
- Type: Integer
- Default value: `100`
- Range: `[1, 100000]`
-- This variable controls the maximum number of plans that can be cached. [Prepared plan cache](/sql-prepared-plan-cache.md) and [non-prepared plan cache](/sql-non-prepared-plan-cache.md) share the same cache.
+- This variable controls the maximum number of plans that can be cached. [Prepared plan cache](/sql-plan-cache.md) and [non-prepared plan cache](/sql-plan-cache.md) share the same cache.
- When you upgrade from an earlier version to a v7.1.0 or later version, this variable remains the same value as [`tidb_prepared_plan_cache_size`](#tidb_prepared_plan_cache_size-new-in-v610)
### tidb_shard_allocate_step New in v5.0
diff --git a/tidb-cloud/monitor-datadog-integration.md b/tidb-cloud/monitor-datadog-integration.md
index 7f1edc90d4759..91ec23f49e177 100644
--- a/tidb-cloud/monitor-datadog-integration.md
+++ b/tidb-cloud/monitor-datadog-integration.md
@@ -60,7 +60,7 @@ Datadog tracks the following metric data for your TiDB clusters.
| tidb_cloud.db_active_connections| gauge | cluster_name: ``
instance: tidb-0\|tidb-1…
component: `tidb` | The number of active connections. |
| tidb_cloud.db_disconnections| gauge | result: ok\|error\|undetermined
cluster_name: ``
instance: tidb-0\|tidb-1…
component: `tidb` | The number of disconnected clients. |
| tidb_cloud.db_command_per_second| gauge | type: Query\|StmtPrepare\|...
cluster_name: ``
instance: tidb-0\|tidb-1…
component: `tidb` | The number of commands processed by TiDB per second, which is classified according to the success or failure of command execution results. |
-| tidb_cloud.db_queries_using_plan_cache_ops| gauge | cluster_name: ``
instance: tidb-0\|tidb-1…
component: `tidb` | The statistics of queries using [Plan Cache](/sql-prepared-plan-cache.md) per second. The execution plan cache only supports the prepared statement command. |
+| tidb_cloud.db_queries_using_plan_cache_ops| gauge | cluster_name: ``
instance: tidb-0\|tidb-1…
component: `tidb` | The statistics of queries using [Plan Cache](/sql-plan-cache.md) per second. The execution plan cache only supports the prepared statement command. |
| tidb_cloud.db_transaction_per_second| gauge | txn_mode: pessimistic\|optimistic
type: abort\|commit\|...
cluster_name: ``
instance: tidb-0\|tidb-1…
component: `tidb` | The number of transactions executed per second. |
| tidb_cloud.node_storage_used_bytes | gauge | cluster_name: ``
instance: tikv-0\|tikv-1…\|tiflash-0\|tiflash-1…
component: tikv\|tiflash | The disk usage of TiKV/TiFlash nodes, in bytes. |
| tidb_cloud.node_storage_capacity_bytes | gauge | cluster_name: ``
instance: tikv-0\|tikv-1…\|tiflash-0\|tiflash-1…
component: tikv\|tiflash | The disk capacity of TiKV/TiFlash nodes, in bytes. |
diff --git a/tidb-cloud/monitor-new-relic-integration.md b/tidb-cloud/monitor-new-relic-integration.md
index b8b6b1c11164d..f47f058e23be2 100644
--- a/tidb-cloud/monitor-new-relic-integration.md
+++ b/tidb-cloud/monitor-new-relic-integration.md
@@ -58,7 +58,7 @@ New Relic tracks the following metric data for your TiDB clusters.
| tidb_cloud.db_active_connections| gauge | cluster_name: ``
instance: tidb-0\|tidb-1…
component: `tidb` | The number of active connections. |
| tidb_cloud.db_disconnections| gauge | result: ok\|error\|undetermined
cluster_name: ``
instance: tidb-0\|tidb-1…
component: `tidb` | The number of disconnected clients. |
| tidb_cloud.db_command_per_second| gauge | type: Query\|StmtPrepare\|...
cluster_name: ``
instance: tidb-0\|tidb-1…
component: `tidb` | The number of commands processed by TiDB per second, which is classified according to the success or failure of command execution results. |
-| tidb_cloud.db_queries_using_plan_cache_ops| gauge | cluster_name: ``
instance: tidb-0\|tidb-1…
component: `tidb` | The statistics of queries using [Plan Cache](/sql-prepared-plan-cache.md) per second. The execution plan cache only supports the prepared statement command. |
+| tidb_cloud.db_queries_using_plan_cache_ops| gauge | cluster_name: ``
instance: tidb-0\|tidb-1…
component: `tidb` | The statistics of queries using [Plan Cache](/sql-plan-cache.md) per second. The execution plan cache only supports the prepared statement command. |
| tidb_cloud.db_transaction_per_second| gauge | txn_mode: pessimistic\|optimistic
type: abort\|commit\|...
cluster_name: ``
instance: tidb-0\|tidb-1…
component: `tidb` | The number of transactions executed per second. |
| tidb_cloud.node_storage_used_bytes | gauge | cluster_name: ``
instance: tikv-0\|tikv-1…\|tiflash-0\|tiflash-1…
component: tikv\|tiflash | The disk usage of TiKV/TiFlash nodes, in bytes. |
| tidb_cloud.node_storage_capacity_bytes | gauge | cluster_name: ``
instance: tikv-0\|tikv-1…\|tiflash-0\|tiflash-1…
component: tikv\|tiflash | The disk capacity of TiKV/TiFlash nodes, in bytes. |
diff --git a/tidb-cloud/tidb-cloud-sql-tuning-overview.md b/tidb-cloud/tidb-cloud-sql-tuning-overview.md
index 0058552892dfc..888c6c21ff1a3 100644
--- a/tidb-cloud/tidb-cloud-sql-tuning-overview.md
+++ b/tidb-cloud/tidb-cloud-sql-tuning-overview.md
@@ -57,7 +57,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 [Prepare Execution Plan Cache](/sql-plan-cache.md).
### Optimize full table scan
diff --git a/tidb-performance-tuning-config.md b/tidb-performance-tuning-config.md
index 234bbbd731386..e6e47d72df636 100644
--- a/tidb-performance-tuning-config.md
+++ b/tidb-performance-tuning-config.md
@@ -26,7 +26,7 @@ This guide describes the non-default settings, including their benefits and pote
The following settings are commonly used to optimize TiDB performance:
-- Enhance execution plan cache, such as [SQL Prepared Execution Plan Cache](/sql-prepared-plan-cache.md), [Non-prepared plan cache](/sql-non-prepared-plan-cache.md), and [Instance-level execution plan cache](/system-variables.md#tidb_enable_instance_plan_cache-new-in-v840).
+- Enhance execution plan cache, such as [SQL Prepared Execution Plan Cache](/sql-plan-cache.md), [Non-prepared plan cache](/sql-plan-cache.md), and [Instance-level execution plan cache](/system-variables.md#tidb_enable_instance_plan_cache-new-in-v840).
- Optimize the behavior of the TiDB optimizer by using [Optimizer Fix Controls](/optimizer-fix-controls.md).
- Use the [Titan](/storage-engine/titan-overview.md) storage engine more aggressively.
@@ -57,7 +57,7 @@ The following table outlines the impact of specific system variable configuratio
| System variable | Description | Note |
| ---------| ---- | ----|
| [`tidb_enable_instance_plan_cache`](/system-variables.md#tidb_enable_instance_plan_cache-new-in-v840) and [`tidb_instance_plan_cache_max_size`](/system-variables.md#tidb_instance_plan_cache_max_size-new-in-v840)| Use instance-level plan cache instead of session-level caching. This significantly improves performance for workloads with high connection counts or frequent prepared statement usage. | This is an experimental feature. Test in non-production environments first and monitor memory usage as the plan cache size increases. |
-| [`tidb_enable_non_prepared_plan_cache`](/system-variables.md#tidb_enable_non_prepared_plan_cache)| Enable the [Non-prepared plan cache](/sql-non-prepared-plan-cache.md) feature to reduce compile costs for applications that do not use prepared statements. | N/A |
+| [`tidb_enable_non_prepared_plan_cache`](/system-variables.md#tidb_enable_non_prepared_plan_cache)| Enable the [Non-prepared plan cache](/sql-plan-cache.md) feature to reduce compile costs for applications that do not use prepared statements. | N/A |
| [`tidb_ignore_prepared_cache_close_stmt`](/system-variables.md#tidb_ignore_prepared_cache_close_stmt-new-in-v600)| Cache plans for applications that use prepared statements but close the plan after each execution. | N/A |
| [`tidb_analyze_column_options`](/system-variables.md#tidb_analyze_column_options-new-in-v830)| Collect statistics for all columns to avoid suboptimal execution plans due to missing column statistics. By default, TiDB only collects statistics for [predicate columns](/statistics.md#collect-statistics-on-some-columns). | Setting this variable to `'ALL'` can cause more resource usage for the `ANALYZE TABLE` operation compared with the default value `'PREDICATE'`. |
| [`tidb_enable_inl_join_inner_multi_pattern`](/system-variables.md#tidb_enable_inl_join_inner_multi_pattern-new-in-v700)| Enable Index Join support when the inner table has `Selection` or `Projection` operators on it. | N/A |
diff --git a/troubleshoot-tidb-oom.md b/troubleshoot-tidb-oom.md
index 1c2f102cd0681..6784f4a100d32 100644
--- a/troubleshoot-tidb-oom.md
+++ b/troubleshoot-tidb-oom.md
@@ -122,7 +122,7 @@ For more information, see [Introduction to Statistics](/statistics.md).
#### Prepared statements are overused
-The client side keeps creating prepared statements but does not execute [`deallocate prepare stmt`](/sql-prepared-plan-cache.md#ignore-the-com_stmt_close-command-and-the-deallocate-prepare-statement), which causes memory consumption to continue to rise and eventually triggers TiDB OOM. The reason is that the memory occupied by a prepared statement is not released until the session is closed. This is especially important for long-time connection sessions.
+The client side keeps creating prepared statements but does not execute [`deallocate prepare stmt`](/sql-plan-cache.md#ignore-the-com_stmt_close-command-and-the-deallocate-prepare-statement), which causes memory consumption to continue to rise and eventually triggers TiDB OOM. The reason is that the memory occupied by a prepared statement is not released until the session is closed. This is especially important for long-time connection sessions.
To solve the problem, consider the following measures: