From 9717d1b40b2f2240c6d386728641d5dc43375b14 Mon Sep 17 00:00:00 2001 From: shichun-0415 Date: Mon, 28 Mar 2022 19:48:59 +0800 Subject: [PATCH 01/19] update SPM doc for SQL plan auto capture --- sql-plan-management.md | 339 +++++++++++++++++++++++++++++------------ system-variables.md | 9 ++ 2 files changed, 252 insertions(+), 96 deletions(-) diff --git a/sql-plan-management.md b/sql-plan-management.md index ec61c65f47f4c..0956696c6b371 100644 --- a/sql-plan-management.md +++ b/sql-plan-management.md @@ -22,42 +22,46 @@ CREATE [GLOBAL | SESSION] BINDING FOR BindableStmt USING BindableStmt This statement binds SQL execution plans at the GLOBAL or SESSION level. Currently, supported bindable SQL statements (BindableStmt) in TiDB include `SELECT`, `DELETE`, `UPDATE`, and `INSERT` / `REPLACE` with `SELECT` subqueries. +> **Note:** +> +> Bindings have higher priority over hints added manually. Therefore, when you execute a statement containing a hint while a binding is present, the hint controlling the behavior of the optimizer does not take effect. However, other types of hints are still effective. + Specifically, two types of these statements cannot be bound to execution plans due to syntax conflicts. See the following examples: ```sql --- Type one: Statements that get the Cartesian product by using the `join` keyword and not specifying the associated columns with the `using` keyword. -create global binding for - select * from t t1 join t t2 -using - select * from t t1 join t t2; - --- Type two: `DELETE` statements that contain the `using` keyword. -create global binding for - delete from t1 using t1 join t2 on t1.a = t2.a -using - delete from t1 using t1 join t2 on t1.a = t2.a; +-- Type one: Statements that get the Cartesian product by using the `JOIN` keyword and not specifying the associated columns with the `USING` keyword. +CREATE GLOBAL BINDING for + SELECT * FROM t t1 JOIN t t2 +USING + SELECT * FROM t t1 JOIN t t2; + +-- Type two: `DELETE` statements that contain the `USING` keyword. +CREATE GLOBAL BINDING for + DELETE FROM t1 USING t1 JOIN t2 ON t1.a = t2.a +USING + DELETE FROM t1 USING t1 JOIN t2 ON t1.a = t2.a; ``` You can bypass syntax conflicts by using equivalent statements. For example, you can rewrite the above statements in the following ways: ```sql --- First rewrite of type one statements: Add a `using` clause for the `join` keyword. -create global binding for - select * from t t1 join t t2 using (a) +-- First rewrite of type one statements: Add a `USING` clause for the `JOIN` keyword. +CREATE GLOBAL BINDING for + SELECT * FROM t t1 JOIN t t2 USING (a) +USING + SELECT * FROM t t1 JOIN t t2 USING (a); + +-- Second rewrite of type one statements: Delete the `JOIN` keyword. +CREATE GLOBAL BINDING for + SELECT * FROM t t1, t t2 +USING + SELECT * FROM t t1, t t2; + +-- Rewrite of type two statements: Remove the `USING` keyword from the `delete` statement. +CREATE GLOBAL BINDING for + DELETE t1 FROM t1 JOIN t2 ON t1.a = t2.a using - select * from t t1 join t t2 using (a); - --- Second rewrite of type one statements: Delete the `join` keyword. -create global binding for - select * from t t1, t t2 -using - select * from t t1, t t2; - --- Rewrite of type two statements: Remove the `using` keyword from the `delete` statement. -create global binding for - delete t1 from t1 join t2 on t1.a = t2.a -using - delete t1 from t1 join t2 on t1.a = t2.a; + DELETE t1 FROM t1 JOIN t2 ON t1.a = t2.a; ``` > **Note:** @@ -68,16 +72,16 @@ Here are two examples: ```sql -- The hint takes effect in the following statement. -create global binding for - insert into t1 select * from t2 where a > 1 and b = 1 +CREATE GLOBAL BINDING for + INSERT INTO t1 SELECT * FROM t2 WHERE a > 1 AND b = 1 using - insert into t1 select /*+ use_index(@sel_1 t2, a) */ * from t2 where a > 1 and b = 1; + INSERT INTO t1 SELECT /*+ use_index(@sel_1 t2, a) */ * FROM t2 WHERE a > 1 AND b = 1; -- The hint cannot take effect in the following statement. -create global binding for - insert into t1 select * from t2 where a > 1 and b = 1 +CREATE GLOBAL BINDING for + INSERT INTO t1 SELECT * FROM t2 WHERE a > 1 AND b = 1 using - insert /*+ use_index(@sel_1 t2, a) */ into t1 select * from t2 where a > 1 and b = 1; + INSERT /*+ use_index(@sel_1 t2, a) */ INTO t1 SELECT * FROM t2 WHERE a > 1 AND b = 1; ``` If you do not specify the scope when creating an execution plan binding, the default scope is SESSION. The TiDB optimizer normalizes bound SQL statements and stores them in the system table. When processing SQL queries, if a normalized statement matches one of the bound SQL statements in the system table and the system variable `tidb_use_plan_baselines` is set to `on` (the default value is `on`), TiDB then uses the corresponding optimizer hint for this statement. If there are multiple matchable execution plans, the optimizer chooses the least costly one to bind. @@ -85,9 +89,9 @@ If you do not specify the scope when creating an execution plan binding, the def `Normalization` is a process that converts a constant in an SQL statement to a variable parameter and explicitly specifies the database for tables referenced in the query, with standardized processing on the spaces and line breaks in the SQL statement. See the following example: ```sql -select * from t where a > 1 +SELECT * FROM t WHERE a > 1 -- After normalization, the above statement is as follows: -select * from test . t where a > ? +SELECT * FROM test . t WHERE a > ? ``` > **Note:** @@ -97,15 +101,15 @@ select * from test . t where a > ? > For example: > > ```sql -> select * from t limit 10 -> select * from t limit 10, 20 -> select * from t where a in (1) -> select * from t where a in (1,2,3) +> SELECT * FROM t limit 10 +> SELECT * FROM t limit 10, 20 +> SELECT * FROM t WHERE a IN (1) +> SELECT * FROM t WHERE a IN (1,2,3) > -- After normalization, the above statements are as follows: -> select * from test . t limit ? -> select * from test . t limit ... -> select * from test . t where a in ( ? ) -> select * from test . t where a in ( ... ) +> SELECT * FROM test . t limit ? +> SELECT * FROM test . t limit ... +> SELECT * FROM test . t WHERE a IN ( ? ) +> SELECT * FROM test . t WHERE a IN ( ... ) > ``` > > When bindings are created, TiDB treats SQL statements that contain a single constant and SQL statements that contain multiple constants joined by commas differently. Therefore, you need to create bindings for the two SQL types separately. @@ -116,25 +120,25 @@ For example: ```sql -- Creates a GLOBAL binding and specifies using `sort merge join` in this binding. -create global binding for - select * from t1, t2 where t1.id = t2.id -using - select /*+ merge_join(t1, t2) */ * from t1, t2 where t1.id = t2.id; +CREATE GLOBAL BINDING for + SELECT * FROM t1, t2 WHERE t1.id = t2.id +USING + SELECT /*+ merge_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; +explain SELECT * FROM t1, t2 WHERE t1.id = t2.id; -- Creates another SESSION binding and specifies using `hash join` in this binding. -create binding for - select * from t1, t2 where t1.id = t2.id -using - select /*+ hash_join(t1, t2) */ * from t1, t2 where t1.id = t2.id; +CREATE BINDING for + SELECT * FROM t1, t2 WHERE t1.id = t2.id +USING + 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; +explain SELECT * FROM t1, t2 WHERE t1.id = t2.id; ``` -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. +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. 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. @@ -142,13 +146,13 @@ In addition, when you create a binding, TiDB requires that the session is in a d The original SQL statement and the bound statement must have the same text after normalization and hint removal, or the binding will fail. Take the following examples: -- This binding can be created successfully because the texts before and after parameterization and hint removal are the same: `select * from test . t where a > ?` +- This binding can be created successfully because the texts before and after parameterization and hint removal are the same: `SELECT * FROM test . t WHERE a > ?` ```sql CREATE BINDING FOR SELECT * FROM t WHERE a > 1 USING SELECT * FROM t use index (idx) WHERE a > 2 ``` -- This binding will fail because the original SQL statement is processed as `select * from test . t where a > ?`, while the bound SQL statement is processed differently as `select * from test . t where b > ?`. +- This binding will fail because the original SQL statement is processed as `SELECT * FROM test . t WHERE a > ?`, while the bound SQL statement is processed differently as `SELECT * FROM test . t WHERE b > ?`. ```sql CREATE BINDING FOR SELECT * FROM t WHERE a > 1 USING SELECT * FROM t use index(idx) WHERE b > 2 @@ -174,10 +178,10 @@ The following example is based on the example in [create binding](#create-a-bind ```sql -- Drops the binding created in the SESSION scope. -drop session binding for select * from t1, t2 where t1.id = t2.id; +drop session binding for SELECT * FROM t1, t2 WHERE t1.id = t2.id; -- Views the SQL execution plan again. -explain 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 `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. @@ -186,6 +190,18 @@ In the example above, the dropped binding in the SESSION scope shields the corre > > Executing `DROP GLOBAL BINDING` drops the binding in the current tidb-server instance cache and changes the status of the corresponding row in the system table to 'deleted'. This statement does not directly delete the records in the system table, because other tidb-server instances need to read the 'deleted' status to drop the corresponding binding in their cache. For the records in these system tables with the status of 'deleted', at every 100 `bind-info-lease` (the default value is `3s`, and `300s` in total) interval, the background thread triggers an operation of reclaiming and clearing on the bindings of `update_time` before 10 `bind-info-lease` (to ensure that all tidb-server instances have read the 'deleted' status and updated the cache). +## Change binding status + +{{< copyable "sql" >}} + +```sql +SET BINDING [ENABLED | DISABLED] FOR BindableStmt; +``` + +You can execute this statement to change the status of a binding. The default status is ENABLED. The effective scope is GLOBAL and cannot be modified. + +When executing this statement, you can only change the status of a binding from `Disabled` to `Enabled` or from `Enabled` to `Disabled`. If there is no binding for you to change the status, a warning message is returned, saying `There are no bindings can be set the status. Please check the SQL text`. Note that a binding in `Disabled` status is not used by any query. + ### View binding {{< copyable "sql" >}} @@ -201,41 +217,98 @@ 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, Invalid, Rejected, and Pending verification| +| status | Status including Enabled (available, replacing Using from v6.0), Disabled (unavailable), Deleted, Invalid, Rejected, and Pending verification| | create_time | Creating time | | update_time | Updating time | | charset | Character set | | collation | Ordering rule | | source | The way in which a binding is created, including `manual` (created by the `create [global] binding` SQL statement), `capture` (captured automatically by TiDB), and `evolve` (evolved automatically by TiDB) | -### Troubleshoot binding +### Troubleshoot bindings -{{< copyable "sql" >}} +You can use either of the following methods to troubleshoot bindings: -```sql -SELECT @@[SESSION.]last_plan_from_binding; -``` +- Use the system variable [`last_plan_from_binding`](/system-variables.md#last_plan_from_binding-new-in-v40) to show whether the execution plan used by the last executed statement is from the binding. -This statement uses the system variable [`last_plan_from_binding`](/system-variables.md#last_plan_from_binding-new-in-v40) to show whether the execution plan used by the last executed statement is from the binding. + {{< copyable "sql" >}} -In addition, when you use the `explain format = 'verbose'` statement to view the query plan of a SQL statement, if the SQL statement uses binding, the `explain` statement will return a warning. In this situation, you can check the warning message to learn which binding is used in the SQL statement. + ```sql + -- Create a global binding + CREATE GLOBAL BINDING for + SELECT * FROM t + USING + SELECT /*+ USE_INDEX(t, idx_a) */ * FROM t; + + SELECT * FROM t; + SELECT @@[SESSION.]last_plan_from_binding; + ``` -```sql --- Create a global binding. + ```sql + +--------------------------+ + | @@last_plan_from_binding | + +--------------------------+ + | 1 | + +--------------------------+ + 1 row in set (0.00 sec) + ``` -create global binding for - select * from t -using - select * from t; +- Use the `explain format = 'verbose'` statement to view the query plan of a SQL statement. If the SQL statement uses a binding, you can run `show warnings` to check which binding is used in the SQL statement. + + ```sql + -- Create a global binding + + CREATE GLOBAL BINDING for + SELECT * FROM t + USING + SELECT /*+ USE_INDEX(t, idx_a) */ * FROM t; + + -- Use explain format = 'verbose' to view the execution plan of a SQL statement + + explain format = 'verbose' SELECT * FROM t; + + -- Run `show warnings` to view the binding used in the query. + + show warnings; + ``` + + ```sql + +-------+------+--------------------------------------------------------------------------+ + | Level | Code | Message | + +-------+------+--------------------------------------------------------------------------+ + | Note | 1105 | Using the bindSQL: SELECT /*+ USE_INDEX(`t` `idx_a`)*/ * FROM `test`.`t` | + +-------+------+--------------------------------------------------------------------------+ + 1 row in set (0.01 sec) + + ``` + +### Cache bindings + +Each TiDB instace has a least recently used (LRU) cache for bindings. The cache capacity is controlled by the system variable [`tidb_mem_quota_binding_cache`](/system-variables.md#tidb_mem_quota_binding_cache-new-in-v60). You can view bindings that are cached in the TiDB instance. + +To view the cache status of bindings, run the `SHOW binding_cache status` statement. In this statement, the effective scope is GLOBAL by default and cannot be modified. This statement returns the number of available bindings in the cache, the total number of available bindings in the system, memory usage of all cached bindings, and the memory quota. + +{{< copyable "sql" >}} + +```sql --- Use the `explain format = 'verbose'` statement to check the SQL execution plan. Check the warning message to view the binding used in the query. +SHOW binding_cache status; +``` -explain format = 'verbose' select * from t; -show warnings; +```sql ++-------------------+-------------------+--------------+--------------+ +| bindings_in_cache | bindings_in_table | memory_usage | memory_quota | ++-------------------+-------------------+--------------+--------------+ +| 1 | 1 | 159 Bytes | 64 MB | ++-------------------+-------------------+--------------+--------------+ +1 row in set (0.00 sec) ``` ## Baseline capturing +Used for [preventing rollback of execution plans during an upgrade](#prevent-rollback-of-execution-plans-during-an-upgrade), this function captures queries that meet capturing conditions and create bindings for them. + +### Enable capturing + To enable baseline capturing, set `tidb_capture_plan_baselines` to `on`. The default value is `off`. > **Note:** @@ -248,7 +321,12 @@ However, TiDB does not automatically capture bindings for the following types of - `EXPLAIN` and `EXPLAIN ANALYZE` statements. - SQL statements executed internally in TiDB, such as `SELECT` queries used for automatically loading statistical information. -- SQL statements that are bound to a manually created execution plan. +- Statements that contain `Enabled` or `Disabled` bindings. +- Statements that meet capturing conditions. + +> **Note:** +> +> Existing bindings are fixed by generating a group of hints. In this way, execution plans generated by query statements do not change. For most OLTP queries, including queries using the same index or Join mode (such as HashJoin and IndexJoin), TiDB guarantees plan consistency before and after binding. However, due to limitations of hints, TiDB cannot guarantee plan consistency for some complex queries, such as Join of more than two tables, MPP queries, and complex OLAP queries. For `PREPARE` / `EXECUTE` statements and for queries executed with binary protocols, TiDB automatically captures bindings for the real query statements, not for the `PREPARE` / `EXECUTE` statements. @@ -256,6 +334,75 @@ For `PREPARE` / `EXECUTE` statements and for queries executed with binary protoc > > Because TiDB has some embedded SQL statements to ensure the correctness of some features, baseline capturing by default automatically shields these SQL statements. +### Filter out bindings + +This function allows you to configure a blocklist to filter out queries that meet the requirements. A blocklist has three dimensions, table name, frequency, and user name. + +#### Usage + +Insert filtering conditions into the system table `mysql.capture_plan_baselines_blacklist`. Then the filtering conditions take effect in the entire cluster immediately. + +```sql +-- Filter by table name + INSERT INTO mysql.capture_plan_baselines_blacklist(filter_type, filter_value) VALUES('table', 'test.t'); + +-- Filter by database name and table name through wildcards + INSERT INTO mysql.capture_plan_baselines_blacklist(filter_type, filter_value) VALUES('table', 'test.table_*'); + INSERT INTO mysql.capture_plan_baselines_blacklist(filter_type, filter_value) VALUES('table', 'db_*.table_*'); + +-- Filter by frequency + INSERT INTO mysql.capture_plan_baselines_blacklist(filter_type, filter_value) VALUES('frequency', '2'); + +-- Filter by user name + INSERT INTO mysql.capture_plan_baselines_blacklist(filter_type, filter_value) VALUES('user', 'user1'); +``` + +| ** Dimension ** | ** Dimension name ** | ** Description ** | Remarks | +| :----------- | :----------- | :----------------------------------------------------------- | ------------------------------------------------------------ | +| Table name | table | Filter by table name. Each filtering rule is in the form of `db.table` and supports wildcards. For details about the rules, see [Plain table names](/table-filter.md# plain-table-names) and [Wildcards](/table-filter.md#wildcards). | Case insensitive. If the table name contains illegal content, the log returns a warning message `[sql-bind] failed to load mysql.capture_plan_baselines_blacklist`. | +| Frequency | frequency | SQL statements executed more than once are captured by default. You can set a high frequency to capture statements more frequently. | Setting frequency to a value smaller than 1 is considered illegal, and the log returns a warning message `[sql-bind] frequency threshold is less than 1, ignore it`. If multiple frequency filter rules are inserted, the value with the highest frequency prevails. | +| User name | user | Statements executed by blocklisted users are not captured. | If multiple users execute the same statement, this statement is not captured only if the user names are all in the blocklist. | + +> **Note:** +> +> - Modifying a blocklist requires the super privilege. +> +> - If the blocklist contains illegal filter content, TiDB returns warning message `[sql-bind] unknown capture filter type, ignore it` in the log. + +### Prevent rollback of execution plans during an upgrade + +When upgrading a TiDB cluster, you can use baseline capturing to prevent rollback of execution plans by performing the following steps: + +1. Enable baseline capturing and keep it working for a period of time. This ensures that most important plans are captured. + + > **Note:** + > + > Test data shows that long-term working of baseline capturing does not affect performance of the cluster load. Therefore, it is recommended to enable baseline capturing as long as possible. + +2. Upgrade the TiDB cluster. After the upgrade, captured bindings work to ensure plan consistency. + +3. After the upgrade, delete bindings as required. + + - Check the binding source by running the [`SHOW BINDINGS`](#view-binding) statement. + + Based on the `Source` field in the output, decide whether the bindings are captured ( `capture`) or manually created (`manual`). + + - Determine whether to retain the captured bindings: + + ``` + -- View the plan with the binding enabled + SET @@SESSION.TIDB_USE_PLAN_BASELINES = true; + EXPLAIN FORMAT='VERBOSE' SELECT * FROM t1 WHERE ...; + + -- View the plan with the binding disabled + SET @@SESSION.TIDB_USE_PLAN_BASELINES = false; + EXPLAIN FORMAT='VERBOSE' SELECT * FROM t1 WHERE ...; + ``` + + - If the execution plan is consistent, you can delete the binding safely. + + - If the execution plan is inconsistent, you need to identify the cause, for examaple, checking operations on statistical information. In this case, you need retain the binding to ensure plan + ## Baseline evolution Baseline evolution is an important feature of SPM introduced in TiDB v4.0. @@ -271,7 +418,7 @@ Use the following statement to enable automatic binding evolution: {{< copyable "sql" >}} ```sql -set global tidb_evolve_plan_baselines = on; +SET GLOBAL tidb_evolve_plan_baselines = ON; ``` The default value of `tidb_evolve_plan_baselines` is `off`. @@ -288,7 +435,7 @@ Assume that table `t` is defined as follows: {{< copyable "sql" >}} ```sql -create table t(a int, b int, key(a), key(b)); +CREATE TABLE t(a INT, b INT, KEY(a), KEY(b)); ``` Perform the following query on table `t`: @@ -296,7 +443,7 @@ Perform the following query on table `t`: {{< copyable "sql" >}} ```sql -select * from t where a < 100 and b < 100; +SELECT * FROM t WHERE a < 100 AND b < 100; ``` In the table defined above, few rows meet the `a < 100` condition. But for some reason, the optimizer mistakenly selects the full table scan instead of the optimal execution plan that uses index `a`. You can first use the following statement to create a binding: @@ -304,7 +451,7 @@ In the table defined above, few rows meet the `a < 100` condition. But for some {{< copyable "sql" >}} ```sql -create global binding for select * from t where a < 100 and b < 100 using select * from t use index(a) where a < 100 and b < 100; +CREATE GLOBAL BINDING for SELECT * FROM t WHERE a < 100 AND b < 100 using SELECT * FROM t use index(a) WHERE a < 100 AND b < 100; ``` When the query above is executed again, the optimizer selects index `a` (influenced by the binding created above) to reduce the query time. @@ -343,18 +490,18 @@ Because the baseline evolution automatically creates a new binding, when the que During cluster upgrade, SQL Plan Management (SPM) might cause compatibility issues and make the upgrade fail. To ensure a successful upgrade, you need to include the following list for upgrade precheck: -* When you upgrade from a version earlier than v5.2.0 (that is, v4.0, v5.0, and v5.1) to the current version, make sure that `tidb_evolve_plan_baselines` is disabled before the upgrade. To disable this variable, perform the following steps. +* When you upgrade from a version earlier than v5.2.0 (that is, v4.0, v5.0, and v5.1) to the current version, make sure that `tidb_evolve_plan_baselines` is disabled before the upgrade. To disable this variable, perform the following steps. {{< copyable "sql" >}} ```sql - -- Check whether `tidb_evolve_plan_baselines` is disabled in the earlier version. - - select @@global.tidb_evolve_plan_baselines; - - -- If `tidb_evolve_plan_baselines` is still enabled, disable it. - - set global tidb_evolve_plan_baselines = off; + -- Check whether `tidb_evolve_plan_baselines` is disabled in the earlier version. + + SELECT @@global.tidb_evolve_plan_baselines; + + -- If `tidb_evolve_plan_baselines` is still enabled, disable it. + + SET GLOBAL tidb_evolve_plan_baselines = OFF; ``` * Before you upgrade from v4.0 to the current version, you need to check whether the syntax of all queries corresponding to the available SQL bindings is correct in the new version. If any syntax errors exist, delete the corresponding SQL binding. To do that, perform the following steps. @@ -363,15 +510,15 @@ During cluster upgrade, SQL Plan Management (SPM) might cause compatibility issu ```sql -- Check the query corresponding to the available SQL binding in the version to be upgraded. - - select bind_sql from mysql.bind_info where status = 'using'; - - -- Verify the result from the above SQL query in the test environment of the new version. - + + SELECT bind_sql FROM mysql.bind_info WHERE status = 'using'; + + -- Verify the result from the above SQL query in the test environment of the new version. + bind_sql_0; bind_sql_1; ... - - -- In the case of a syntax error (ERROR 1064 (42000): You have an error in your SQL syntax), delete the corresponding binding. - -- For any other errors (for example, tables are not found), it means that the syntax is compatible. No other operation is needed. + + -- In the case of a syntax error (ERROR 1064 (42000): You have an error in your SQL syntax), delete the corresponding binding. + -- For any other errors (for example, tables are not found), it means that the syntax is compatible. No other operation is needed. ``` diff --git a/system-variables.md b/system-variables.md index d0d4ae2d38344..fdabeb7d376a3 100644 --- a/system-variables.md +++ b/system-variables.md @@ -1204,6 +1204,15 @@ For a system upgraded to v5.0 from an earlier version, if you have not modified - This variable is used to set the memory usage threshold of the local cache in the `Apply` operator. - The local cache in the `Apply` operator is used to speed up the computation of the `Apply` operator. You can set the variable to `0` to disable the `Apply` cache feature. +### `tidb_mem_quota_binding_cache` (New in v6.0) + +- Scope: GLOBAL +- Default value: `67108864` (64 MiB) +- Range: `[0, 2147483647]` +- Unit: Bytes +- This variable is used to set the threshold of the memory used for caching bindings. +- If a system creates or captures excessive bindings, resulting in overuse of memory space, TiDB returns a warning in the log. In this case, the cache cannot hold all available bindings or determine which bindings to store. For this reason, some queries may have no bindings. To address this problem, you can increase the value of this parameter, which will increase the memory space used for caching bindings. After modifying this parameter, you need to run `admin reload bindings` to reload bindings and validate the modification. + ### tidb_mem_quota_query - Scope: SESSION From 821d6b38757fbd12bbb6481f88430693e82baf8d Mon Sep 17 00:00:00 2001 From: shichun-0415 <89768198+shichun-0415@users.noreply.github.com> Date: Tue, 29 Mar 2022 10:53:54 +0800 Subject: [PATCH 02/19] fix jenkins --- sql-plan-management.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql-plan-management.md b/sql-plan-management.md index 0956696c6b371..eac80b63ad802 100644 --- a/sql-plan-management.md +++ b/sql-plan-management.md @@ -357,7 +357,7 @@ Insert filtering conditions into the system table `mysql.capture_plan_baselines_ INSERT INTO mysql.capture_plan_baselines_blacklist(filter_type, filter_value) VALUES('user', 'user1'); ``` -| ** Dimension ** | ** Dimension name ** | ** Description ** | Remarks | +| ** Dimension** | ** Dimension name** | ** Description** | Remarks | | :----------- | :----------- | :----------------------------------------------------------- | ------------------------------------------------------------ | | Table name | table | Filter by table name. Each filtering rule is in the form of `db.table` and supports wildcards. For details about the rules, see [Plain table names](/table-filter.md# plain-table-names) and [Wildcards](/table-filter.md#wildcards). | Case insensitive. If the table name contains illegal content, the log returns a warning message `[sql-bind] failed to load mysql.capture_plan_baselines_blacklist`. | | Frequency | frequency | SQL statements executed more than once are captured by default. You can set a high frequency to capture statements more frequently. | Setting frequency to a value smaller than 1 is considered illegal, and the log returns a warning message `[sql-bind] frequency threshold is less than 1, ignore it`. If multiple frequency filter rules are inserted, the value with the highest frequency prevails. | From 371ed5e5d942dffd1566e9e9b756a9b416e60309 Mon Sep 17 00:00:00 2001 From: shichun-0415 <89768198+shichun-0415@users.noreply.github.com> Date: Tue, 29 Mar 2022 11:03:49 +0800 Subject: [PATCH 03/19] fix jenkins --- sql-plan-management.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql-plan-management.md b/sql-plan-management.md index eac80b63ad802..67b1791b003eb 100644 --- a/sql-plan-management.md +++ b/sql-plan-management.md @@ -357,7 +357,7 @@ Insert filtering conditions into the system table `mysql.capture_plan_baselines_ INSERT INTO mysql.capture_plan_baselines_blacklist(filter_type, filter_value) VALUES('user', 'user1'); ``` -| ** Dimension** | ** Dimension name** | ** Description** | Remarks | +| **Dimension** | **Dimension name** | **Description** | Remarks | | :----------- | :----------- | :----------------------------------------------------------- | ------------------------------------------------------------ | | Table name | table | Filter by table name. Each filtering rule is in the form of `db.table` and supports wildcards. For details about the rules, see [Plain table names](/table-filter.md# plain-table-names) and [Wildcards](/table-filter.md#wildcards). | Case insensitive. If the table name contains illegal content, the log returns a warning message `[sql-bind] failed to load mysql.capture_plan_baselines_blacklist`. | | Frequency | frequency | SQL statements executed more than once are captured by default. You can set a high frequency to capture statements more frequently. | Setting frequency to a value smaller than 1 is considered illegal, and the log returns a warning message `[sql-bind] frequency threshold is less than 1, ignore it`. If multiple frequency filter rules are inserted, the value with the highest frequency prevails. | From 88a2654a686bf9b12f3198dde2c01d99fd06e09a Mon Sep 17 00:00:00 2001 From: shichun-0415 <89768198+shichun-0415@users.noreply.github.com> Date: Wed, 30 Mar 2022 17:32:02 +0800 Subject: [PATCH 04/19] Update sql-plan-management.md --- sql-plan-management.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql-plan-management.md b/sql-plan-management.md index 67b1791b003eb..7ec4d072e1130 100644 --- a/sql-plan-management.md +++ b/sql-plan-management.md @@ -326,7 +326,7 @@ However, TiDB does not automatically capture bindings for the following types of > **Note:** > -> Existing bindings are fixed by generating a group of hints. In this way, execution plans generated by query statements do not change. For most OLTP queries, including queries using the same index or Join mode (such as HashJoin and IndexJoin), TiDB guarantees plan consistency before and after binding. However, due to limitations of hints, TiDB cannot guarantee plan consistency for some complex queries, such as Join of more than two tables, MPP queries, and complex OLAP queries. +> Currently, a binding generates a group of hints to fix an execution plan generated by a query statement. In this way, the execution plan does not change. For most OLTP queries, including queries using the same index or Join algorithm (such as HashJoin and IndexJoin), TiDB guarantees plan consistency before and after the binding. However, due to the limitations of hints, TiDB cannot guarantee plan consistency for some complex queries, such as Join of more than two tables, MPP queries, and complex OLAP queries. For `PREPARE` / `EXECUTE` statements and for queries executed with binary protocols, TiDB automatically captures bindings for the real query statements, not for the `PREPARE` / `EXECUTE` statements. From 0642b73cb8edcf08e9443a5bdfa4b006cefbd179 Mon Sep 17 00:00:00 2001 From: shichun-0415 <89768198+shichun-0415@users.noreply.github.com> Date: Thu, 31 Mar 2022 15:55:11 +0800 Subject: [PATCH 05/19] Apply suggestions from code review Co-authored-by: Chengpeng Yan <41809508+Reminiscent@users.noreply.github.com> --- sql-plan-management.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sql-plan-management.md b/sql-plan-management.md index 7ec4d072e1130..d56d74a2e77fb 100644 --- a/sql-plan-management.md +++ b/sql-plan-management.md @@ -371,7 +371,7 @@ Insert filtering conditions into the system table `mysql.capture_plan_baselines_ ### Prevent rollback of execution plans during an upgrade -When upgrading a TiDB cluster, you can use baseline capturing to prevent rollback of execution plans by performing the following steps: +When upgrading a TiDB cluster, you can use baseline capturing to prevent regression of execution plans by performing the following steps: 1. Enable baseline capturing and keep it working for a period of time. This ensures that most important plans are captured. @@ -383,9 +383,9 @@ When upgrading a TiDB cluster, you can use baseline capturing to prevent rollbac 3. After the upgrade, delete bindings as required. - - Check the binding source by running the [`SHOW BINDINGS`](#view-binding) statement. + - Check the binding source by running the [`SHOW GLOBAL BINDINGS`](#view-binding) statement. - Based on the `Source` field in the output, decide whether the bindings are captured ( `capture`) or manually created (`manual`). + Based on the `Source` field in the output, decide whether the bindings are captured (`capture`) or manually created (`manual`). - Determine whether to retain the captured bindings: @@ -401,7 +401,7 @@ When upgrading a TiDB cluster, you can use baseline capturing to prevent rollbac - If the execution plan is consistent, you can delete the binding safely. - - If the execution plan is inconsistent, you need to identify the cause, for examaple, checking operations on statistical information. In this case, you need retain the binding to ensure plan + - If the execution plan is inconsistent, you need to identify the cause, for examaple, checking operations on statistical information. In this case, you need retain the binding to ensure plan consistency. ## Baseline evolution From 1778b25ea72aa9f57b93fd5f847aca93ebf9b97b Mon Sep 17 00:00:00 2001 From: shichun-0415 Date: Thu, 31 Mar 2022 16:06:46 +0800 Subject: [PATCH 06/19] Address tech review comments --- sql-plan-management.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sql-plan-management.md b/sql-plan-management.md index d56d74a2e77fb..61565bb130b56 100644 --- a/sql-plan-management.md +++ b/sql-plan-management.md @@ -285,7 +285,7 @@ You can use either of the following methods to troubleshoot bindings: Each TiDB instace has a least recently used (LRU) cache for bindings. The cache capacity is controlled by the system variable [`tidb_mem_quota_binding_cache`](/system-variables.md#tidb_mem_quota_binding_cache-new-in-v60). You can view bindings that are cached in the TiDB instance. -To view the cache status of bindings, run the `SHOW binding_cache status` statement. In this statement, the effective scope is GLOBAL by default and cannot be modified. This statement returns the number of available bindings in the cache, the total number of available bindings in the system, memory usage of all cached bindings, and the memory quota. +To view the cache status of bindings, run the `SHOW binding_cache status` statement. In this statement, the effective scope is GLOBAL by default and cannot be modified. This statement returns the number of available bindings in the cache, the total number of available bindings in the system, memory usage of all cached bindings, and the total memory. {{< copyable "sql" >}} @@ -305,7 +305,7 @@ SHOW binding_cache status; ## Baseline capturing -Used for [preventing rollback of execution plans during an upgrade](#prevent-rollback-of-execution-plans-during-an-upgrade), this function captures queries that meet capturing conditions and create bindings for them. +Used for [preventing regression of execution plans during an upgrade](#prevent-regression-of-execution-plans-during-an-upgrade), this function captures queries that meet capturing conditions and create bindings for them. ### Enable capturing @@ -369,15 +369,15 @@ Insert filtering conditions into the system table `mysql.capture_plan_baselines_ > > - If the blocklist contains illegal filter content, TiDB returns warning message `[sql-bind] unknown capture filter type, ignore it` in the log. -### Prevent rollback of execution plans during an upgrade +### Prevent regression of execution plans during an upgrade When upgrading a TiDB cluster, you can use baseline capturing to prevent regression of execution plans by performing the following steps: -1. Enable baseline capturing and keep it working for a period of time. This ensures that most important plans are captured. +1. Enable baseline capturing and keep it working for a period of time. > **Note:** > - > Test data shows that long-term working of baseline capturing does not affect performance of the cluster load. Therefore, it is recommended to enable baseline capturing as long as possible. + > Test data shows that long-term working of baseline capturing does not affect performance of the cluster load. Therefore, it is recommended to enable baseline capturing as long as possible so that important plans are captured. 2. Upgrade the TiDB cluster. After the upgrade, captured bindings work to ensure plan consistency. From 1f908fc76e5c15b54977e074fe3873d9b3bc9f37 Mon Sep 17 00:00:00 2001 From: shichun-0415 <89768198+shichun-0415@users.noreply.github.com> Date: Thu, 31 Mar 2022 16:08:38 +0800 Subject: [PATCH 07/19] Update sql-plan-management.md Co-authored-by: Chengpeng Yan <41809508+Reminiscent@users.noreply.github.com> --- sql-plan-management.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql-plan-management.md b/sql-plan-management.md index 61565bb130b56..802c3586ab48b 100644 --- a/sql-plan-management.md +++ b/sql-plan-management.md @@ -24,7 +24,7 @@ This statement binds SQL execution plans at the GLOBAL or SESSION level. Current > **Note:** > -> Bindings have higher priority over hints added manually. Therefore, when you execute a statement containing a hint while a binding is present, the hint controlling the behavior of the optimizer does not take effect. However, other types of hints are still effective. +> Bindings have higher priority over manually added hints. Therefore, when you execute a statement containing a hint while a binding is present, the hint controlling the behavior of the optimizer does not take effect. However, other types of hints are still effective. Specifically, two types of these statements cannot be bound to execution plans due to syntax conflicts. See the following examples: From 82e862d565338b40649c5f1d39b5bc26aed3e43f Mon Sep 17 00:00:00 2001 From: shichun-0415 Date: Thu, 31 Mar 2022 16:10:46 +0800 Subject: [PATCH 08/19] Update sql-plan-management.md --- sql-plan-management.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql-plan-management.md b/sql-plan-management.md index 61565bb130b56..e605711382f99 100644 --- a/sql-plan-management.md +++ b/sql-plan-management.md @@ -202,7 +202,7 @@ You can execute this statement to change the status of a binding. The default st When executing this statement, you can only change the status of a binding from `Disabled` to `Enabled` or from `Enabled` to `Disabled`. If there is no binding for you to change the status, a warning message is returned, saying `There are no bindings can be set the status. Please check the SQL text`. Note that a binding in `Disabled` status is not used by any query. -### View binding +### View bindings {{< copyable "sql" >}} @@ -224,7 +224,7 @@ This statement outputs the execution plan bindings at the GLOBAL or SESSION leve | collation | Ordering rule | | source | The way in which a binding is created, including `manual` (created by the `create [global] binding` SQL statement), `capture` (captured automatically by TiDB), and `evolve` (evolved automatically by TiDB) | -### Troubleshoot bindings +### Troubleshoot a binding You can use either of the following methods to troubleshoot bindings: @@ -283,7 +283,7 @@ You can use either of the following methods to troubleshoot bindings: ### Cache bindings -Each TiDB instace has a least recently used (LRU) cache for bindings. The cache capacity is controlled by the system variable [`tidb_mem_quota_binding_cache`](/system-variables.md#tidb_mem_quota_binding_cache-new-in-v60). You can view bindings that are cached in the TiDB instance. +Each TiDB instance has a least recently used (LRU) cache for bindings. The cache capacity is controlled by the system variable [`tidb_mem_quota_binding_cache`](/system-variables.md#tidb_mem_quota_binding_cache-new-in-v60). You can view bindings that are cached in the TiDB instance. To view the cache status of bindings, run the `SHOW binding_cache status` statement. In this statement, the effective scope is GLOBAL by default and cannot be modified. This statement returns the number of available bindings in the cache, the total number of available bindings in the system, memory usage of all cached bindings, and the total memory. From 740e6362d14e90a60b91333b532fd8a400b69730 Mon Sep 17 00:00:00 2001 From: shichun-0415 <89768198+shichun-0415@users.noreply.github.com> Date: Thu, 31 Mar 2022 16:17:45 +0800 Subject: [PATCH 09/19] Update sql-plan-management.md Co-authored-by: Chengpeng Yan <41809508+Reminiscent@users.noreply.github.com> --- sql-plan-management.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql-plan-management.md b/sql-plan-management.md index 85f14353267f7..c4d87adb7bd54 100644 --- a/sql-plan-management.md +++ b/sql-plan-management.md @@ -226,7 +226,7 @@ This statement outputs the execution plan bindings at the GLOBAL or SESSION leve ### Troubleshoot a binding -You can use either of the following methods to troubleshoot bindings: +You can use either of the following methods to troubleshoot a binding: - Use the system variable [`last_plan_from_binding`](/system-variables.md#last_plan_from_binding-new-in-v40) to show whether the execution plan used by the last executed statement is from the binding. From f0c537cbf1d502e16d821f4711e100a35bfe26fb Mon Sep 17 00:00:00 2001 From: shichun-0415 <89768198+shichun-0415@users.noreply.github.com> Date: Thu, 31 Mar 2022 16:37:07 +0800 Subject: [PATCH 10/19] Apply suggestions from code review Co-authored-by: Chengpeng Yan <41809508+Reminiscent@users.noreply.github.com> --- sql-plan-management.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql-plan-management.md b/sql-plan-management.md index c4d87adb7bd54..881dfb63accb2 100644 --- a/sql-plan-management.md +++ b/sql-plan-management.md @@ -383,7 +383,7 @@ When upgrading a TiDB cluster, you can use baseline capturing to prevent regress 3. After the upgrade, delete bindings as required. - - Check the binding source by running the [`SHOW GLOBAL BINDINGS`](#view-binding) statement. + - Check the binding source by running the [`SHOW GLOBAL BINDINGS`](#view-bindings) statement. Based on the `Source` field in the output, decide whether the bindings are captured (`capture`) or manually created (`manual`). From 80ec19fb56c4580c2425eb8bf47d1def42982586 Mon Sep 17 00:00:00 2001 From: shichun-0415 Date: Thu, 31 Mar 2022 16:39:33 +0800 Subject: [PATCH 11/19] Simplify filter dimension table --- sql-plan-management.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sql-plan-management.md b/sql-plan-management.md index 881dfb63accb2..0e92ea70955fb 100644 --- a/sql-plan-management.md +++ b/sql-plan-management.md @@ -357,11 +357,11 @@ Insert filtering conditions into the system table `mysql.capture_plan_baselines_ INSERT INTO mysql.capture_plan_baselines_blacklist(filter_type, filter_value) VALUES('user', 'user1'); ``` -| **Dimension** | **Dimension name** | **Description** | Remarks | -| :----------- | :----------- | :----------------------------------------------------------- | ------------------------------------------------------------ | -| Table name | table | Filter by table name. Each filtering rule is in the form of `db.table` and supports wildcards. For details about the rules, see [Plain table names](/table-filter.md# plain-table-names) and [Wildcards](/table-filter.md#wildcards). | Case insensitive. If the table name contains illegal content, the log returns a warning message `[sql-bind] failed to load mysql.capture_plan_baselines_blacklist`. | -| Frequency | frequency | SQL statements executed more than once are captured by default. You can set a high frequency to capture statements more frequently. | Setting frequency to a value smaller than 1 is considered illegal, and the log returns a warning message `[sql-bind] frequency threshold is less than 1, ignore it`. If multiple frequency filter rules are inserted, the value with the highest frequency prevails. | -| User name | user | Statements executed by blocklisted users are not captured. | If multiple users execute the same statement, this statement is not captured only if the user names are all in the blocklist. | +| **Dimension name** | **Description** | Remarks | +| :----------- | :----------------------------------------------------------- | ------------------------------------------------------------ | +| table | Filter by table name. Each filtering rule is in the form of `db.table` and supports wildcards. For details about the rules, see [Plain table names](/table-filter.md# plain-table-names) and [Wildcards](/table-filter.md#wildcards). | Case insensitive. If the table name contains illegal content, the log returns a warning message `[sql-bind] failed to load mysql.capture_plan_baselines_blacklist`. | +| frequency | Filter by frequency. SQL statements executed more than once are captured by default. You can set a high frequency to capture statements more frequently. | Setting frequency to a value smaller than 1 is considered illegal, and the log returns a warning message `[sql-bind] frequency threshold is less than 1, ignore it`. If multiple frequency filter rules are inserted, the value with the highest frequency prevails. | +| user | Filter by user name. Statements executed by blocklisted users are not captured. | If multiple users execute the same statement, this statement is not captured only if the user names are all in the blocklist. | > **Note:** > From ec90602fa06500677dc278add7a439ad3f4c4855 Mon Sep 17 00:00:00 2001 From: shichun-0415 <89768198+shichun-0415@users.noreply.github.com> Date: Thu, 31 Mar 2022 17:08:25 +0800 Subject: [PATCH 12/19] Update sql-plan-management.md --- sql-plan-management.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql-plan-management.md b/sql-plan-management.md index 0e92ea70955fb..24b7fd03094b4 100644 --- a/sql-plan-management.md +++ b/sql-plan-management.md @@ -377,7 +377,7 @@ When upgrading a TiDB cluster, you can use baseline capturing to prevent regress > **Note:** > - > Test data shows that long-term working of baseline capturing does not affect performance of the cluster load. Therefore, it is recommended to enable baseline capturing as long as possible so that important plans are captured. + > Test data shows that long-term working of baseline capturing does not affect performance of the cluster load. Therefore, it is recommended to enable baseline capturing as long as possible so that important plans (appear twice or above) are captured. 2. Upgrade the TiDB cluster. After the upgrade, captured bindings work to ensure plan consistency. From 4b5370405e1bb884d9b9a40c858d54eba39089cb Mon Sep 17 00:00:00 2001 From: shichun-0415 <89768198+shichun-0415@users.noreply.github.com> Date: Thu, 31 Mar 2022 21:55:35 +0800 Subject: [PATCH 13/19] Apply suggestions from code review Co-authored-by: Grace Cai --- sql-plan-management.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sql-plan-management.md b/sql-plan-management.md index 24b7fd03094b4..c0d4e7df98b68 100644 --- a/sql-plan-management.md +++ b/sql-plan-management.md @@ -24,7 +24,7 @@ This statement binds SQL execution plans at the GLOBAL or SESSION level. Current > **Note:** > -> Bindings have higher priority over manually added hints. Therefore, when you execute a statement containing a hint while a binding is present, the hint controlling the behavior of the optimizer does not take effect. However, other types of hints are still effective. +> Bindings have higher priority over manually added hints. Therefore, when you execute a statement containing a hint while a corresponding binding is present, the hint controlling the behavior of the optimizer does not take effect. However, other types of hints are still effective. Specifically, two types of these statements cannot be bound to execution plans due to syntax conflicts. See the following examples: @@ -198,9 +198,9 @@ In the example above, the dropped binding in the SESSION scope shields the corre SET BINDING [ENABLED | DISABLED] FOR BindableStmt; ``` -You can execute this statement to change the status of a binding. The default status is ENABLED. The effective scope is GLOBAL and cannot be modified. +You can execute this statement to change the status of a binding. The default status is ENABLED. The effective scope is GLOBAL by default and cannot be modified. -When executing this statement, you can only change the status of a binding from `Disabled` to `Enabled` or from `Enabled` to `Disabled`. If there is no binding for you to change the status, a warning message is returned, saying `There are no bindings can be set the status. Please check the SQL text`. Note that a binding in `Disabled` status is not used by any query. +When executing this statement, you can only change the status of a binding from `Disabled` to `Enabled` or from `Enabled` to `Disabled`. If no binding is available for status changes, a warning message is returned, saying `There are no bindings can be set the status. Please check the SQL text`. Note that a binding in `Disabled` status is not used by any query. ### View bindings @@ -217,7 +217,7 @@ 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 Enabled (available, replacing Using from v6.0), Disabled (unavailable), Deleted, Invalid, Rejected, and Pending verification| +| status | Status including Enabled (replacing the Using status from v6.0), Disabled, Deleted, Invalid, Rejected, and Pending verification| | create_time | Creating time | | update_time | Updating time | | charset | Character set | @@ -285,7 +285,7 @@ You can use either of the following methods to troubleshoot a binding: Each TiDB instance has a least recently used (LRU) cache for bindings. The cache capacity is controlled by the system variable [`tidb_mem_quota_binding_cache`](/system-variables.md#tidb_mem_quota_binding_cache-new-in-v60). You can view bindings that are cached in the TiDB instance. -To view the cache status of bindings, run the `SHOW binding_cache status` statement. In this statement, the effective scope is GLOBAL by default and cannot be modified. This statement returns the number of available bindings in the cache, the total number of available bindings in the system, memory usage of all cached bindings, and the total memory. +To view the cache status of bindings, run the `SHOW binding_cache status` statement. In this statement, the effective scope is GLOBAL by default and cannot be modified. This statement returns the number of available bindings in the cache, the total number of available bindings in the system, memory usage of all cached bindings, and the total memory for the cache. {{< copyable "sql" >}} @@ -305,7 +305,7 @@ SHOW binding_cache status; ## Baseline capturing -Used for [preventing regression of execution plans during an upgrade](#prevent-regression-of-execution-plans-during-an-upgrade), this function captures queries that meet capturing conditions and create bindings for them. +Used for [preventing regression of execution plans during an upgrade](#prevent-regression-of-execution-plans-during-an-upgrade), this feature captures queries that meet capturing conditions and creates bindings for these queries. ### Enable capturing @@ -322,11 +322,11 @@ However, TiDB does not automatically capture bindings for the following types of - `EXPLAIN` and `EXPLAIN ANALYZE` statements. - SQL statements executed internally in TiDB, such as `SELECT` queries used for automatically loading statistical information. - Statements that contain `Enabled` or `Disabled` bindings. -- Statements that meet capturing conditions. +- Statements that are filtered out by capturing conditions. > **Note:** > -> Currently, a binding generates a group of hints to fix an execution plan generated by a query statement. In this way, the execution plan does not change. For most OLTP queries, including queries using the same index or Join algorithm (such as HashJoin and IndexJoin), TiDB guarantees plan consistency before and after the binding. However, due to the limitations of hints, TiDB cannot guarantee plan consistency for some complex queries, such as Join of more than two tables, MPP queries, and complex OLAP queries. +> Currently, a binding generates a group of hints to fix an execution plan generated by a query statement. In this way, for the same query, the execution plan does not change. For most OLTP queries, including queries using the same index or Join algorithm (such as HashJoin and IndexJoin), TiDB guarantees plan consistency before and after the binding. However, due to the limitations of hints, TiDB cannot guarantee plan consistency for some complex queries, such as Join of more than two tables, MPP queries, and complex OLAP queries. For `PREPARE` / `EXECUTE` statements and for queries executed with binary protocols, TiDB automatically captures bindings for the real query statements, not for the `PREPARE` / `EXECUTE` statements. @@ -336,7 +336,7 @@ For `PREPARE` / `EXECUTE` statements and for queries executed with binary protoc ### Filter out bindings -This function allows you to configure a blocklist to filter out queries that meet the requirements. A blocklist has three dimensions, table name, frequency, and user name. +This feature allows you to configure a blocklist to filter out queries whose bindings you do not want to capture. A blocklist has three dimensions, table name, frequency, and user name. #### Usage From 5a44f31b96ab940e8258a3b7aee17948c421000c Mon Sep 17 00:00:00 2001 From: shichun-0415 <89768198+shichun-0415@users.noreply.github.com> Date: Thu, 31 Mar 2022 21:56:25 +0800 Subject: [PATCH 14/19] Update sql-plan-management.md --- sql-plan-management.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql-plan-management.md b/sql-plan-management.md index c0d4e7df98b68..359e0361e2faf 100644 --- a/sql-plan-management.md +++ b/sql-plan-management.md @@ -401,7 +401,7 @@ When upgrading a TiDB cluster, you can use baseline capturing to prevent regress - If the execution plan is consistent, you can delete the binding safely. - - If the execution plan is inconsistent, you need to identify the cause, for examaple, checking operations on statistical information. In this case, you need retain the binding to ensure plan consistency. + - If the execution plan is inconsistent, you need to identify the cause, for examaple, checking operations on statistical information. In this case, you need to retain the binding to ensure plan consistency. ## Baseline evolution From 64bf2db555414703fba819cdc2468a4bc07dd1f2 Mon Sep 17 00:00:00 2001 From: shichun-0415 <89768198+shichun-0415@users.noreply.github.com> Date: Fri, 1 Apr 2022 11:48:13 +0800 Subject: [PATCH 15/19] Apply suggestions from code review Co-authored-by: Grace Cai --- sql-plan-management.md | 12 ++++++------ system-variables.md | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sql-plan-management.md b/sql-plan-management.md index 359e0361e2faf..da2f58b4bf7c6 100644 --- a/sql-plan-management.md +++ b/sql-plan-management.md @@ -359,7 +359,7 @@ Insert filtering conditions into the system table `mysql.capture_plan_baselines_ | **Dimension name** | **Description** | Remarks | | :----------- | :----------------------------------------------------------- | ------------------------------------------------------------ | -| table | Filter by table name. Each filtering rule is in the form of `db.table` and supports wildcards. For details about the rules, see [Plain table names](/table-filter.md# plain-table-names) and [Wildcards](/table-filter.md#wildcards). | Case insensitive. If the table name contains illegal content, the log returns a warning message `[sql-bind] failed to load mysql.capture_plan_baselines_blacklist`. | +| table | Filter by table name. Each filtering rule is in the `db.table` format. The supported filtering syntax includes [Plain table names](/table-filter.md#plain-table-names) and [Wildcards](/table-filter.md#wildcards). | Case insensitive. If a table name contains illegal characters, the log returns a warning message `[sql-bind] failed to load mysql.capture_plan_baselines_blacklist`. | | frequency | Filter by frequency. SQL statements executed more than once are captured by default. You can set a high frequency to capture statements more frequently. | Setting frequency to a value smaller than 1 is considered illegal, and the log returns a warning message `[sql-bind] frequency threshold is less than 1, ignore it`. If multiple frequency filter rules are inserted, the value with the highest frequency prevails. | | user | Filter by user name. Statements executed by blocklisted users are not captured. | If multiple users execute the same statement, this statement is not captured only if the user names are all in the blocklist. | @@ -367,11 +367,11 @@ Insert filtering conditions into the system table `mysql.capture_plan_baselines_ > > - Modifying a blocklist requires the super privilege. > -> - If the blocklist contains illegal filter content, TiDB returns warning message `[sql-bind] unknown capture filter type, ignore it` in the log. +> - If a blocklist contains illegal filters, TiDB returns the warning message `[sql-bind] unknown capture filter type, ignore it` in the log. ### Prevent regression of execution plans during an upgrade -When upgrading a TiDB cluster, you can use baseline capturing to prevent regression of execution plans by performing the following steps: + Before upgrading a TiDB cluster, you can use baseline capturing to prevent regression of execution plans by performing the following steps: 1. Enable baseline capturing and keep it working for a period of time. @@ -379,13 +379,13 @@ When upgrading a TiDB cluster, you can use baseline capturing to prevent regress > > Test data shows that long-term working of baseline capturing does not affect performance of the cluster load. Therefore, it is recommended to enable baseline capturing as long as possible so that important plans (appear twice or above) are captured. -2. Upgrade the TiDB cluster. After the upgrade, captured bindings work to ensure plan consistency. +2. Upgrade the TiDB cluster. After the upgrade, TiDB uses those captured bindings to ensure execution plan consistency. 3. After the upgrade, delete bindings as required. - Check the binding source by running the [`SHOW GLOBAL BINDINGS`](#view-bindings) statement. - Based on the `Source` field in the output, decide whether the bindings are captured (`capture`) or manually created (`manual`). + In the output, check the `Source` field to see whether a binding is captured (`capture`) or manually created (`manual`). - Determine whether to retain the captured bindings: @@ -401,7 +401,7 @@ When upgrading a TiDB cluster, you can use baseline capturing to prevent regress - If the execution plan is consistent, you can delete the binding safely. - - If the execution plan is inconsistent, you need to identify the cause, for examaple, checking operations on statistical information. In this case, you need to retain the binding to ensure plan consistency. + - If the execution plan is inconsistent, you need to identify the cause, for example, by checking statistics. In this case, you need to retain the binding to ensure plan consistency. ## Baseline evolution diff --git a/system-variables.md b/system-variables.md index fdabeb7d376a3..108d30535bcf4 100644 --- a/system-variables.md +++ b/system-variables.md @@ -1204,14 +1204,14 @@ For a system upgraded to v5.0 from an earlier version, if you have not modified - This variable is used to set the memory usage threshold of the local cache in the `Apply` operator. - The local cache in the `Apply` operator is used to speed up the computation of the `Apply` operator. You can set the variable to `0` to disable the `Apply` cache feature. -### `tidb_mem_quota_binding_cache` (New in v6.0) +### tidb_mem_quota_binding_cache (New in v6.0.0) - Scope: GLOBAL - Default value: `67108864` (64 MiB) - Range: `[0, 2147483647]` - Unit: Bytes - This variable is used to set the threshold of the memory used for caching bindings. -- If a system creates or captures excessive bindings, resulting in overuse of memory space, TiDB returns a warning in the log. In this case, the cache cannot hold all available bindings or determine which bindings to store. For this reason, some queries may have no bindings. To address this problem, you can increase the value of this parameter, which will increase the memory space used for caching bindings. After modifying this parameter, you need to run `admin reload bindings` to reload bindings and validate the modification. +- If a system creates or captures excessive bindings, resulting in overuse of memory space, TiDB returns a warning in the log. In this case, the cache cannot hold all available bindings or determine which bindings to store. For this reason, some queries might miss their bindings. To address this problem, you can increase the value of this variable, which increases the memory used for caching bindings. After modifying this parameter, you need to run `admin reload bindings` to reload bindings and validate the modification. ### tidb_mem_quota_query From 8e0a1ea02f2ff7457bd2ab9ae92739ef80ba5728 Mon Sep 17 00:00:00 2001 From: shichun-0415 <89768198+shichun-0415@users.noreply.github.com> Date: Fri, 1 Apr 2022 17:12:16 +0800 Subject: [PATCH 16/19] Apply suggestions from code review --- sql-plan-management.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql-plan-management.md b/sql-plan-management.md index da2f58b4bf7c6..2edc611e03b8b 100644 --- a/sql-plan-management.md +++ b/sql-plan-management.md @@ -361,7 +361,7 @@ Insert filtering conditions into the system table `mysql.capture_plan_baselines_ | :----------- | :----------------------------------------------------------- | ------------------------------------------------------------ | | table | Filter by table name. Each filtering rule is in the `db.table` format. The supported filtering syntax includes [Plain table names](/table-filter.md#plain-table-names) and [Wildcards](/table-filter.md#wildcards). | Case insensitive. If a table name contains illegal characters, the log returns a warning message `[sql-bind] failed to load mysql.capture_plan_baselines_blacklist`. | | frequency | Filter by frequency. SQL statements executed more than once are captured by default. You can set a high frequency to capture statements more frequently. | Setting frequency to a value smaller than 1 is considered illegal, and the log returns a warning message `[sql-bind] frequency threshold is less than 1, ignore it`. If multiple frequency filter rules are inserted, the value with the highest frequency prevails. | -| user | Filter by user name. Statements executed by blocklisted users are not captured. | If multiple users execute the same statement, this statement is not captured only if the user names are all in the blocklist. | +| user | Filter by user name. Statements executed by blocklisted users are not captured. | If multiple users execute the same statement and their user names are all in the blocklist, this statement is captured. | > **Note:** > From ab27e56a3d500998c2832b86821aaf464f684dc5 Mon Sep 17 00:00:00 2001 From: shichun-0415 <89768198+shichun-0415@users.noreply.github.com> Date: Fri, 1 Apr 2022 17:22:53 +0800 Subject: [PATCH 17/19] Apply suggestions from code review --- sql-plan-management.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql-plan-management.md b/sql-plan-management.md index 2edc611e03b8b..a6da9d76a9c33 100644 --- a/sql-plan-management.md +++ b/sql-plan-management.md @@ -360,7 +360,7 @@ Insert filtering conditions into the system table `mysql.capture_plan_baselines_ | **Dimension name** | **Description** | Remarks | | :----------- | :----------------------------------------------------------- | ------------------------------------------------------------ | | table | Filter by table name. Each filtering rule is in the `db.table` format. The supported filtering syntax includes [Plain table names](/table-filter.md#plain-table-names) and [Wildcards](/table-filter.md#wildcards). | Case insensitive. If a table name contains illegal characters, the log returns a warning message `[sql-bind] failed to load mysql.capture_plan_baselines_blacklist`. | -| frequency | Filter by frequency. SQL statements executed more than once are captured by default. You can set a high frequency to capture statements more frequently. | Setting frequency to a value smaller than 1 is considered illegal, and the log returns a warning message `[sql-bind] frequency threshold is less than 1, ignore it`. If multiple frequency filter rules are inserted, the value with the highest frequency prevails. | +| frequency | Filter by frequency. SQL statements executed more than once are captured by default. You can set a high frequency to capture statements that are frequently executed. | Setting frequency to a value smaller than 1 is considered illegal, and the log returns a warning message `[sql-bind] frequency threshold is less than 1, ignore it`. If multiple frequency filter rules are inserted, the value with the highest frequency prevails. | | user | Filter by user name. Statements executed by blocklisted users are not captured. | If multiple users execute the same statement and their user names are all in the blocklist, this statement is captured. | > **Note:** @@ -377,7 +377,7 @@ Insert filtering conditions into the system table `mysql.capture_plan_baselines_ > **Note:** > - > Test data shows that long-term working of baseline capturing does not affect performance of the cluster load. Therefore, it is recommended to enable baseline capturing as long as possible so that important plans (appear twice or above) are captured. + > Test data shows that long-term working of baseline capturing has a slight impact on the performance of the cluster load. Therefore, it is recommended to enable baseline capturing as long as possible so that important plans (appear twice or above) are captured. 2. Upgrade the TiDB cluster. After the upgrade, TiDB uses those captured bindings to ensure execution plan consistency. From 8209b59cf1cc848d0975194c02e113e05531a17e Mon Sep 17 00:00:00 2001 From: shichun-0415 <89768198+shichun-0415@users.noreply.github.com> Date: Fri, 1 Apr 2022 17:29:27 +0800 Subject: [PATCH 18/19] change v60 to v600 --- sql-plan-management.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql-plan-management.md b/sql-plan-management.md index a6da9d76a9c33..eb018db954b3f 100644 --- a/sql-plan-management.md +++ b/sql-plan-management.md @@ -283,7 +283,7 @@ You can use either of the following methods to troubleshoot a binding: ### Cache bindings -Each TiDB instance has a least recently used (LRU) cache for bindings. The cache capacity is controlled by the system variable [`tidb_mem_quota_binding_cache`](/system-variables.md#tidb_mem_quota_binding_cache-new-in-v60). You can view bindings that are cached in the TiDB instance. +Each TiDB instance has a least recently used (LRU) cache for bindings. The cache capacity is controlled by the system variable [`tidb_mem_quota_binding_cache`](/system-variables.md#tidb_mem_quota_binding_cache-new-in-v600). You can view bindings that are cached in the TiDB instance. To view the cache status of bindings, run the `SHOW binding_cache status` statement. In this statement, the effective scope is GLOBAL by default and cannot be modified. This statement returns the number of available bindings in the cache, the total number of available bindings in the system, memory usage of all cached bindings, and the total memory for the cache. From 98887e848fe159b6eef22b8a7df33fabb9af6b87 Mon Sep 17 00:00:00 2001 From: shichun-0415 <89768198+shichun-0415@users.noreply.github.com> Date: Fri, 1 Apr 2022 19:44:46 +0800 Subject: [PATCH 19/19] Update sql-plan-management.md --- sql-plan-management.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql-plan-management.md b/sql-plan-management.md index eb018db954b3f..8f7be10ccd162 100644 --- a/sql-plan-management.md +++ b/sql-plan-management.md @@ -361,7 +361,7 @@ Insert filtering conditions into the system table `mysql.capture_plan_baselines_ | :----------- | :----------------------------------------------------------- | ------------------------------------------------------------ | | table | Filter by table name. Each filtering rule is in the `db.table` format. The supported filtering syntax includes [Plain table names](/table-filter.md#plain-table-names) and [Wildcards](/table-filter.md#wildcards). | Case insensitive. If a table name contains illegal characters, the log returns a warning message `[sql-bind] failed to load mysql.capture_plan_baselines_blacklist`. | | frequency | Filter by frequency. SQL statements executed more than once are captured by default. You can set a high frequency to capture statements that are frequently executed. | Setting frequency to a value smaller than 1 is considered illegal, and the log returns a warning message `[sql-bind] frequency threshold is less than 1, ignore it`. If multiple frequency filter rules are inserted, the value with the highest frequency prevails. | -| user | Filter by user name. Statements executed by blocklisted users are not captured. | If multiple users execute the same statement and their user names are all in the blocklist, this statement is captured. | +| user | Filter by user name. Statements executed by blocklisted users are not captured. | If multiple users execute the same statement and their user names are all in the blocklist, this statement is not captured. | > **Note:** >