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
2 changes: 1 addition & 1 deletion TOC.md
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@
- [Optimizer Hints](/optimizer-hints.md)
- [Follower Read](/follower-read.md)
- [Check the TiDB Cluster Status Using SQL Statements](/check-cluster-status-using-sql-statements.md)
- [Execution Plan Binding](/execution-plan-binding.md)
- [SQL Plan Management](/sql-plan-management.md)
- [Access Tables Using `IndexMerge`](/index-merge.md)
- [Statement Summary Table](/statement-summary-tables.md)
- [Coprocessor Cache](/coprocessor-cache.md)
Expand Down
75 changes: 57 additions & 18 deletions execution-plan-binding.md → sql-plan-management.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
---
title: Execution Plan Binding
summary: Learn about execution plan binding operations in TiDB.
title: SQL Plan Management (SPM)
summary: Learn about SQL Plan Management in TiDB.
category: reference
aliases: ['/docs/stable/reference/performance/execution-plan-bind/']
aliases: ['/docs/stable/reference/performance/execution-plan-bind/','/docs/stable/execution-plan-binding/']
---

# Execution Plan Binding
# SQL Plan Management (SPM)

The [Optimizer Hints](/optimizer-hints.md) document introduces how to select a specific execution plan using Hint. However, sometimes you need to interfere with execution selection without modifying SQL statements. Execution Plan Binding provides a set of functionalities to do this.
SQL Plan Management is a set of functions that execute SQL bindings to manually interfere with SQL execution plans. These functions include SQL binding, baseline capturing, and baseline evolution.

## Syntax
## SQL binding

### Create binding
An SQL binding is the basis of SPM. The [Optimizer Hints](/optimizer-hints.md) document introduces how to select a specific execution plan using hints. However, sometimes you need to interfere with execution selection without modifying SQL statements. With SQL bindings, you can select a specified execution plan without modifying SQL statements.

### Create a binding

{{< copyable "sql" >}}

Expand All @@ -30,7 +32,7 @@ For example:
create global binding for
select * from t1, t2 where t1.id = t2.id
using
select /*+ TIDB_SMJ(t1, t2) */ * from t1, t2 where t1.id = t2.id;
select /*+ sm_join(t1, t2) */ * from t1, t2 where t1.id = t2.id;

-- The execution plan of this SQL statement uses the `sort merge join` specified in the GLOBAL binding.
explain select * from t1, t2 where t1.id = t2.id;
Expand All @@ -39,15 +41,15 @@ explain select * from t1, t2 where t1.id = t2.id;
create binding for
select * from t1, t2 where t1.id = t2.id
using
select /*+ TIDB_HJ(t1, t2) */ * from t1, t2 where t1.id = t2.id;
select /*+ hash_join(t1, t2) */ * from t1, t2 where t1.id = t2.id;

-- In the execution plan of this statement, `hash join` specified in the SESSION binding is used, instead of `sort merge join` specified in the GLOBAL binding.
explain select * from t1, t2 where t1.id = t2.id;
```

When the first `select` statement is being executed, the optimizer adds the `TIDB_SMJ(t1, t2)` hint to the statement through the binding in the GLOBAL scope. The top node of the execution plan in the `explain` result is MergeJoin. When the second `select` statement is being executed, the optimizer uses the binding in the SESSION scope instead of the binding in the GLOBAL scope and adds the `TIDB_HJ(t1, t2)` hint to the statement. The top node of the execution plan in the `explain` result is HashJoin.
When the first `select` statement is being executed, the optimizer adds the `sm_join(t1, t2)` hint to the statement through the binding in the GLOBAL scope. The top node of the execution plan in the `explain` result is MergeJoin. When the second `select` statement is being executed, the optimizer uses the binding in the SESSION scope instead of the binding in the GLOBAL scope and adds the `hash_join(t1, t2)` hint to the statement. The top node of the execution plan in the `explain` result is HashJoin.

`Parameterization` is a process that converts a constant in SQL to a variable parameter, with standardized processing on the spaces and line breaks in the SQL statement, for example,
`Parameterization` is a process that converts a constant in an SQL statement to a variable parameter, with standardized processing on the spaces and line breaks in the SQL statement, for example,

{{< copyable "sql" >}}

Expand All @@ -57,6 +59,10 @@ select * from t where a > 1
select * from t where a > ?
```

Each standardized SQL statement can have only one binding created using `CREATE BINDING` at a time. When multiple bindings are created for the same standardized SQL statement, the last created binding is retained, and all previous bindings (created and evolved) are marked as deleted. But session bindings and global bindings can coexist and are not affected by this logic.

In addition, when you create a binding, TiDB requires that the session is in a database context, which means that a database is specified when the client is connected or `use ${database}` is executed.

> **Note:**
>
> The text must be the same before and after parameterization and hint removal for both the original SQL statement and the bound statement, or the binding will fail. Take the following examples:
Expand Down Expand Up @@ -95,7 +101,7 @@ drop session binding for select * from t1, t2 where t1.id = t2.id;
explain select * from t1,t2 where t1.id = t2.id;
```

In the example above, the dropped binding in the SESSION scope shields the corresponding binding in the GLOBAL scope. The optimizer does not add the `TIDB_SMJ(t1, t2)` hint to the statement. The top node of the execution plan in the `explain` result is not fixed to MergeJoin by this hint. Instead, the top node is independently selected by the optimizer according to the cost estimation.
In the example above, the dropped binding in the SESSION scope shields the corresponding binding in the GLOBAL scope. The optimizer does not add the `sm_join(t1, t2)` hint to the statement. The top node of the execution plan in the `explain` result is not fixed to MergeJoin by this hint. Instead, the top node is independently selected by the optimizer according to the cost estimation.

### View binding

Expand All @@ -112,25 +118,37 @@ This statement outputs the execution plan bindings at the GLOBAL or SESSION leve
| original_sql | Original SQL statement after parameterization |
| bind_sql | Bound SQL statement with hints |
| default_db | Default database |
| status | Status including Using, Deleted, and Invalid |
| status | Status including Using, Deleted, Invalid, Rejected, and Pending verification|
| create_time | Creating time |
| update_time | Updating time |
| charset | Character set |
| collation | Ordering rule |

### Automatically create binding
## Baseline capturing

To enable automatic binding creation, set `tidb_capture_plan_baselines` to `on`. The default value is `off`.
To enable baseline capturing, set `tidb_capture_plan_baselines` to `on`. The default value is `off`.

> **Note:**
>
> Because the automatic binding creation function relies on [Statement Summary](/statement-summary-tables.md), make sure to enable Statement Summary before using automatic binding.

After automatic binding creation is enabled, the historical SQL statements in the Statement Summary are traversed every `bind-info-lease` (the default value is `3s`), and bindings are automatically created for SQL statements that appear at least twice.
After automatic binding creation is enabled, the historical SQL statements in the Statement Summary are traversed every `bind-info-lease` (the default value is `3s`), and baseline capturing is automatically created for SQL statements that appear at least twice.

> **Note:**
>
> Because TiDB has some embedded SQL statements to ensure the correctness of some features, baseline capturing by default automatically shields these SQL statements.

## Baseline evolution

Baseline evolution is an important feature of SPM introduced in TiDB v4.0.0-rc.

As data updates, the previously bound execution plan might no longer be optimal. The baseline evolution feature can automatically optimize the bound execution plan.

### Automatically evolve binding
In addition, baseline evolution, to a certain extent, can also avoid the jitter brought to the execution plan caused by the change of statistical information.

As data updates, the previously bound execution plan might no longer be optimal. The automatic binding evolution feature can optimize the bound execution plan. Use the following statement to enable automatic binding evolution:
### Usage

Use the following statement to enable automatic binding evolution:

{{< copyable "sql" >}}

Expand Down Expand Up @@ -180,3 +198,24 @@ To reduce the impact that the automatic evolution has on clusters, use the follo

- Set `tidb_evolve_plan_task_max_time` to limit the maximum execution time of each execution plan. The default value is `600s`.
- Set `tidb_evolve_plan_task_start_time` (`00:00 +0000` by default) and `tidb_evolve_plan_task_end_time` (`23:59 +0000` by default) to limit the time window.

### Notes

Because the baseline evolution automatically creates a new binding, when the query environment changes, the automatically created binding might have multiple behavior choices. Pay attention to the following notes:

+ Baseline evolution only evolves standardized SQL statements that have at least one global binding.

+ Because creating a new binding deletes all previous bindings (for a standardized SQL statement), the automatically evolved binding will be deleted after manually creating a new binding.

+ All hints related to the calculation process are retained during the evolution. These hints are as follows:

| Hint | Description |
| :-------- | :------------- |
| `memory_quota` | The maximum memory that can be used for a query. |
| `use_toja` | Whether the optimizer transforms sub-queries to Join. |
| `use_cascades` | Whether to use the cascades optimizer. |
| `no_index_merge` | Whether the optimizer uses Index Merge as an option for reading tables. |
| `read_consistent_replica` | Whether to forcibly enable Follower Read when reading tables. |
| `max_execution_time` | The longest duration for a query. |

+ `read_from_storage` is a special hint in that it specifies whether to read data from TiKV or from TiFlash when reading tables. Because TiDB provides isolation reads, when the isolation condition changes, this hint has a great influence on the evolved execution plan. Therefore, when this hint exists in the initially created binding, TiDB ignores all its evolved bindings.