diff --git a/sql-plan-management.md b/sql-plan-management.md index 956c283f91bf6..6bfb8d3db6d40 100644 --- a/sql-plan-management.md +++ b/sql-plan-management.md @@ -231,25 +231,25 @@ The original SQL statement and the bound statement must have the same text after #### Create a binding according to a historical execution plan -To make the execution plan of a SQL statement fixed to a historical execution plan, you can use `plan_digest` to bind that historical execution plan to the SQL statement, which is more convenient than binding it according to a SQL statement. +To make the execution plan of a SQL statement fixed to a historical execution plan, you can use Plan Digest to bind that historical execution plan to the SQL statement, which is more convenient than binding it according to a SQL statement. Besides, you can create bindings for multiple SQL statements at once. For more detailed introductions and more examples, refer to [CREATE [GLOBAL|SESSION] BINDING](/sql-statements/sql-statement-create-binding.md). When using this feature, note the following: - The feature generates hints according to historical execution plans and uses the generated hints for binding. Because historical execution plans are stored in [Statement Summary Tables](/statement-summary-tables.md), before using this feature, you need to enable the [`tidb_enable_stmt_summary`](/system-variables.md#tidb_enable_stmt_summary-new-in-v304) system variable first. - For TiFlash queries, Join queries with three or more tables, and queries that contain subqueries, the auto-generated hints are not adequate, which might result in the plan not being fully bound. In such cases, a warning will occur when creating a binding. -- If a historical execution plan is for a SQL statement with hints, the hints will be added to the binding. For example, after executing `SELECT /*+ max_execution_time(1000) */ * FROM t`, the binding created with its `plan_digest` will include `max_execution_time(1000)`. +- If a historical execution plan is for a SQL statement with hints, the hints will be added to the binding. For example, after executing `SELECT /*+ max_execution_time(1000) */ * FROM t`, the binding created with its Plan Digest will include `max_execution_time(1000)`. The SQL statement of this binding method is as follows: ```sql -CREATE [GLOBAL | SESSION] BINDING FROM HISTORY USING PLAN DIGEST 'plan_digest'; +CREATE [GLOBAL | SESSION] BINDING FROM HISTORY USING PLAN DIGEST StringLiteralOrUserVariableList; ``` -This statement binds an execution plan to a SQL statement using `plan_digest`. The default scope is SESSION. The applicable SQL statements, priorities, scopes, and effective conditions of the created bindings are the same as that of [bindings created according to SQL statements](#create-a-binding-according-to-a-sql-statement). +This statement binds an execution plan to a SQL statement using Plan Digest. The default scope is SESSION. The applicable SQL statements, priorities, scopes, and effective conditions of the created bindings are the same as that of [bindings created according to SQL statements](#create-a-binding-according-to-a-sql-statement). -To use this binding method, you need to first get the `plan_digest` corresponding to the target historical execution plan in `statements_summary`, and then create a binding using the `plan_digest`. The detailed steps are as follows: +To use this binding method, you need to first get the Plan Digest corresponding to the target historical execution plan in `statements_summary`, and then create a binding using the Plan Digest. The detailed steps are as follows: -1. Get the `plan_digest` corresponding to the target execution plan in `statements_summary`. +1. Get the Plan Digest corresponding to the target execution plan in `statements_summary`. For example: @@ -274,9 +274,9 @@ To use this binding method, you need to first get the `plan_digest` correspondin BINARY_PLAN: 6QOYCuQDCg1UYWJsZVJlYWRlcl83Ev8BCgtTZWxlY3Rpb25fNhKOAQoPBSJQRnVsbFNjYW5fNSEBAAAAOA0/QSkAAQHwW4jDQDgCQAJKCwoJCgR0ZXN0EgF0Uh5rZWVwIG9yZGVyOmZhbHNlLCBzdGF0czpwc2V1ZG9qInRpa3ZfdGFzazp7dGltZTo1NjAuOMK1cywgbG9vcHM6MH1w////CQMEAXgJCBD///8BIQFzCDhVQw19BAAkBX0QUg9lcSgBfCAudC5hLCAxKWrmYQAYHOi0gc6hBB1hJAFAAVIQZGF0YTo9GgRaFAW4HDQuMDVtcywgCbYcMWKEAWNvcF8F2agge251bTogMSwgbWF4OiA1OTguNsK1cywgcHJvY19rZXlzOiAwLCBycGNfBSkAMgkMBVcQIDYwOS4pEPBDY29wcl9jYWNoZV9oaXRfcmF0aW86IDAuMDAsIGRpc3RzcWxfY29uY3VycmVuY3k6IDE1fXCwAXj///////////8BGAE= ``` - In this example, you can see that the execution plan corresponding to `plan_digest` is `4e3159169cc63c14b139a4e7d72eae1759875c9a9581f94bb2079aae961189cb`. + In this example, you can see that the execution plan corresponding to Plan Digest is `4e3159169cc63c14b139a4e7d72eae1759875c9a9581f94bb2079aae961189cb`. -2. Use `plan_digest` to create a binding: +2. Use Plan Digest to create a binding: ```sql CREATE BINDING FROM HISTORY USING PLAN DIGEST '4e3159169cc63c14b139a4e7d72eae1759875c9a9581f94bb2079aae961189cb'; @@ -317,7 +317,7 @@ SELECT @@LAST_PLAN_FROM_BINDING; ### Remove a binding -You can remove a binding according to a SQL statement or `sql_digest`. +You can remove a binding according to a SQL statement or SQL Digest. #### Remove a binding according to a SQL statement @@ -343,15 +343,15 @@ 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. -#### Remove a binding according to `sql_digest` +#### Remove a binding according to SQL Digest -In addition to removing a binding according to a SQL statement, you can also remove a binding according to `sql_digest`. +In addition to removing a binding according to a SQL statement, you can also remove a binding according to SQL Digest. For more detailed introductions and more examples, refer to [DROP [GLOBAL|SESSION] BINDING](/sql-statements/sql-statement-drop-binding.md). ```sql -DROP [GLOBAL | SESSION] BINDING FOR SQL DIGEST 'sql_digest'; +DROP [GLOBAL | SESSION] BINDING FOR SQL DIGEST StringLiteralOrUserVariableList; ``` -This statement removes an execution plan binding corresponding to `sql_digest` at the GLOBAL or SESSION level. The default scope is SESSION. You can get the `sql_digest` by [viewing bindings](#view-bindings). +This statement removes an execution plan binding corresponding to SQL Digest at the GLOBAL or SESSION level. The default scope is SESSION. You can get the SQL Digest by [viewing bindings](#view-bindings). > **Note:** > diff --git a/sql-statements/sql-statement-create-binding.md b/sql-statements/sql-statement-create-binding.md index fcf3dc8ce70d8..268d18f51d42a 100644 --- a/sql-statements/sql-statement-create-binding.md +++ b/sql-statements/sql-statement-create-binding.md @@ -17,13 +17,19 @@ The bound SQL statement is parameterized and stored in the system table. When a ```ebnf+diagram CreateBindingStmt ::= 'CREATE' GlobalScope 'BINDING' ( 'FOR' BindableStmt 'USING' BindableStmt -| 'FROM' 'HISTORY' 'USING' 'PLAN' 'DIGEST' PlanDigest ) +| 'FROM' 'HISTORY' 'USING' 'PLAN' 'DIGEST' StringLiteralOrUserVariableList ) GlobalScope ::= ( 'GLOBAL' | 'SESSION' )? BindableStmt ::= ( SelectStmt | UpdateStmt | InsertIntoStmt | ReplaceIntoStmt | DeleteStmt ) + +StringLiteralOrUserVariableList: + (StringLitOrUserVariable | StringLiteralOrUserVariableList ',' StringLitOrUserVariable) + +StringLiteralOrUserVariable: + stringLiteral | UserVariable ``` **** @@ -32,6 +38,8 @@ BindableStmt ::= You can create a binding according to a SQL statement or a historical execution plan. +When you want to create a binding according to a historical execution plan, you need to specify the corresponding Plan Digest. You can use string literals or user variables of string type to specify Plan Digests. You can specify multiple Plan Digests to create bindings for multiple statements at the same time. In this cases, you can specify multiple string values, and each string value can also contain multiple digests, and they should be separated by comma. + The following example shows how to create a binding according to a SQL statement. {{< copyable "sql" >}} @@ -139,34 +147,163 @@ mysql> EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; The following example shows how to create a binding according to a historical execution plan. ```sql -mysql> CREATE TABLE t(id INT PRIMARY KEY , a INT, KEY(a)); -Query OK, 0 rows affected (0.06 sec) +USE test; +CREATE TABLE t1(a INT, b INT, c INT, INDEX ia(a)); +CREATE TABLE t2(a INT, b INT, c INT, INDEX ia(a)); +INSERT INTO t1 SELECT * FROM t2 WHERE a = 1; +SELECT @@LAST_PLAN_FROM_BINDING; +UPDATE /*+ INL_JOIN(t2) */ t1, t2 SET t1.a = 1 WHERE t1.b = t2.a; +SELECT @@LAST_PLAN_FROM_BINDING; +DELETE /*+ HASH_JOIN(t1) */ t1 FROM t1 JOIN t2 WHERE t1.b = t2.a; +SELECT @@LAST_PLAN_FROM_BINDING; +SELECT * FROM t1 WHERE t1.a IN (SELECT a FROM t2); +SELECT @@LAST_PLAN_FROM_BINDING; +``` + +Method 1: +```sql +SELECT query_sample_text, stmt_type, table_names, plan_digest FROM information_schema.statements_summary_history WHERE table_names LIKE '%test.t1%' AND stmt_type != 'CreateTable'; +CREATE GLOBAL BINDING FROM HISTORY USING PLAN DIGEST 'e72819cf99932f63a548156dbf433adda60e10337e89dcaa8638b4caf16f64d8,c291edc36b2482738d3389d335f37efc76290be2930330fe5034c5f4c42eeb36,8dc146249484f4a6ab219bfe9effa6b7a18aeed3764d49b610da61ac347ab914,73b2dec866595688ea416675f88ccb3456eb8e7443a79cd816695b688e07ac6b'; +``` + +Method 2: +```sql +SELECT @digests:=GROUP_CONCAT(plan_digest) FROM information_schema.statements_summary_history WHERE table_names LIKE '%test.t1%' AND stmt_type != 'CreateTable'; +CREATE GLOBAL BINDING FROM HISTORY USING PLAN DIGEST @digests; +``` + +```sql +SHOW GLOBAL BINDINGS; +INSERT INTO t1 SELECT * FROM t2 WHERE a = 1; +SELECT @@LAST_PLAN_FROM_BINDING; +UPDATE t1, t2 SET t1.a = 1 WHERE t1.b = t2.a; +SELECT @@LAST_PLAN_FROM_BINDING; +DELETE t1 FROM t1 JOIN t2 WHERE t1.b = t2.a; +SELECT @@LAST_PLAN_FROM_BINDING; +SELECT * FROM t1 WHERE t1.a IN (SELECT a FROM t2); +SELECT @@LAST_PLAN_FROM_BINDING; +``` + +```sql +> CREATE TABLE t1(a INT, b INT, c INT, INDEX ia(a)); +Query OK, 0 rows affected (0.048 sec) + +> CREATE TABLE t2(a INT, b INT, c INT, INDEX ia(a)); +Query OK, 0 rows affected (0.035 sec) -mysql> SELECT /*+ IGNORE_INDEX(t, a) */ * FROM t WHERE a = 1; -Empty set (0.01 sec) +> INSERT INTO t1 SELECT * FROM t2 WHERE a = 1; +Query OK, 0 rows affected (0.002 sec) +Records: 0 Duplicates: 0 Warnings: 0 + +> SELECT @@LAST_PLAN_FROM_BINDING; ++--------------------------+ +| @@LAST_PLAN_FROM_BINDING | ++--------------------------+ +| 0 | ++--------------------------+ +1 row in set (0.001 sec) -mysql> SELECT plan_digest FROM INFORMATION_SCHEMA.STATEMENTS_SUMMARY WHERE QUERY_SAMPLE_TEXT = 'SELECT /*+ IGNORE_INDEX(t, a) */ * FROM t WHERE a = 1'; -+------------------------------------------------------------------+ -| plan_digest | -+------------------------------------------------------------------+ -| 4e3159169cc63c14b139a4e7d72eae1759875c9a9581f94bb2079aae961189cb | -+------------------------------------------------------------------+ -1 row in set (0.01 sec) +> UPDATE /*+ INL_JOIN(t2) */ t1, t2 SET t1.a = 1 WHERE t1.b = t2.a; +Query OK, 0 rows affected (0.005 sec) +Rows matched: 0 Changed: 0 Warnings: 0 -mysql> CREATE BINDING FROM HISTORY USING PLAN DIGEST '4e3159169cc63c14b139a4e7d72eae1759875c9a9581f94bb2079aae961189cb'; -Query OK, 0 rows affected (0.02 sec) +> SELECT @@LAST_PLAN_FROM_BINDING; ++--------------------------+ +| @@LAST_PLAN_FROM_BINDING | ++--------------------------+ +| 0 | ++--------------------------+ +1 row in set (0.000 sec) -mysql> SELECT * FROM t WHERE a = 1; -Empty set (0.01 sec) +> DELETE /*+ HASH_JOIN(t1) */ t1 FROM t1 JOIN t2 WHERE t1.b = t2.a; +Query OK, 0 rows affected (0.003 sec) -mysql> SELECT @@LAST_PLAN_FROM_BINDING; +> SELECT @@LAST_PLAN_FROM_BINDING; ++--------------------------+ +| @@LAST_PLAN_FROM_BINDING | ++--------------------------+ +| 0 | ++--------------------------+ +1 row in set (0.000 sec) + +> SELECT * FROM t1 WHERE t1.a IN (SELECT a FROM t2); +Empty set (0.002 sec) + +> SELECT @@LAST_PLAN_FROM_BINDING; ++--------------------------+ +| @@LAST_PLAN_FROM_BINDING | ++--------------------------+ +| 0 | ++--------------------------+ +1 row in set (0.001 sec) + +> SELECT @digests:=GROUP_CONCAT(plan_digest) FROM information_schema.statements_summary_history WHERE table_names LIKE '%test.t1%' AND stmt_type != 'CreateTable'; ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| @digests:=GROUP_CONCAT(plan_digest) | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 73b2dec866595688ea416675f88ccb3456eb8e7443a79cd816695b688e07ac6b,8dc146249484f4a6ab219bfe9effa6b7a18aeed3764d49b610da61ac347ab914,c291edc36b2482738d3389d335f37efc76290be2930330fe5034c5f4c42eeb36,e72819cf99932f63a548156dbf433adda60e10337e89dcaa8638b4caf16f64d8 | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +1 row in set (0.001 sec) + +> CREATE GLOBAL BINDING FROM HISTORY USING PLAN DIGEST @digests; +Query OK, 0 rows affected (0.060 sec) + +> SHOW GLOBAL BINDINGS; ++----------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------+---------+-------------------------+-------------------------+---------+-----------------+---------+------------------------------------------------------------------+------------------------------------------------------------------+ +| Original_sql | Bind_sql | Default_db | Status | Create_time | Update_time | Charset | Collation | Source | Sql_digest | Plan_digest | ++----------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------+---------+-------------------------+-------------------------+---------+-----------------+---------+------------------------------------------------------------------+------------------------------------------------------------------+ +| insert into `test` . `t1` select * from `test` . `t2` where `a` = ? | INSERT INTO `test`.`t1` SELECT /*+ use_index(@`sel_1` `test`.`t2` `ia`) no_order_index(@`sel_1` `test`.`t2` `ia`)*/ * FROM `test`.`t2` WHERE `a` = 1 | test | enabled | 2024-08-11 05:27:19.669 | 2024-08-11 05:27:19.669 | utf8 | utf8_general_ci | history | bd23e6af17e7b77b25383e50e258f0dece18583d19772f08caacb2021945a300 | e72819cf99932f63a548156dbf433adda60e10337e89dcaa8638b4caf16f64d8 | +| update ( `test` . `t1` ) join `test` . `t2` set `t1` . `a` = ? where `t1` . `b` = `t2` . `a` | UPDATE /*+ inl_join(`test`.`t2`) use_index(@`upd_1` `test`.`t1` ) use_index(@`upd_1` `test`.`t2` `ia`) no_order_index(@`upd_1` `test`.`t2` `ia`)*/ (`test`.`t1`) JOIN `test`.`t2` SET `t1`.`a`=1 WHERE `t1`.`b` = `t2`.`a` | test | enabled | 2024-08-11 05:27:19.667 | 2024-08-11 05:27:19.667 | utf8 | utf8_general_ci | history | 987e91af17eb40e36fecfc0634cce0b6a736de02bb009091810f932804fc02e9 | c291edc36b2482738d3389d335f37efc76290be2930330fe5034c5f4c42eeb36 | +| delete `test` . `t1` from `test` . `t1` join `test` . `t2` where `t1` . `b` = `t2` . `a` | DELETE /*+ hash_join_build(`test`.`t2`) use_index(@`del_1` `test`.`t1` ) use_index(@`del_1` `test`.`t2` )*/ `test`.`t1` FROM `test`.`t1` JOIN `test`.`t2` WHERE `t1`.`b` = `t2`.`a` | test | enabled | 2024-08-11 05:27:19.664 | 2024-08-11 05:27:19.664 | utf8 | utf8_general_ci | history | 70ef3d442d95c51020a76c7c86a3ab674258606d4dd24bbd16ac6f69d87a4316 | 8dc146249484f4a6ab219bfe9effa6b7a18aeed3764d49b610da61ac347ab914 | +| select * from `test` . `t1` where `t1` . `a` in ( select `a` from `test` . `t2` ) | SELECT /*+ use_index(@`sel_1` `test`.`t1` ) stream_agg(@`sel_2`) use_index(@`sel_2` `test`.`t2` `ia`) order_index(@`sel_2` `test`.`t2` `ia`) agg_to_cop(@`sel_2`)*/ * FROM `test`.`t1` WHERE `t1`.`a` IN (SELECT `a` FROM `test`.`t2`) | test | enabled | 2024-08-11 05:27:19.649 | 2024-08-11 05:27:19.649 | utf8 | utf8_general_ci | history | b58508a5e29d7889adf98cad50343d7a575fd32ad55dbdaa88e14ecde54f3d93 | 73b2dec866595688ea416675f88ccb3456eb8e7443a79cd816695b688e07ac6b | ++----------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------+---------+-------------------------+-------------------------+---------+-----------------+---------+------------------------------------------------------------------+------------------------------------------------------------------+ +4 rows in set (0.001 sec) + +> INSERT INTO t1 SELECT * FROM t2 WHERE a = 1; +Query OK, 0 rows affected (0.002 sec) +Records: 0 Duplicates: 0 Warnings: 0 + +> SELECT @@LAST_PLAN_FROM_BINDING; ++--------------------------+ +| @@LAST_PLAN_FROM_BINDING | ++--------------------------+ +| 1 | ++--------------------------+ +1 row in set (0.000 sec) + +> UPDATE t1, t2 SET t1.a = 1 WHERE t1.b = t2.a; +Query OK, 0 rows affected (0.002 sec) +Rows matched: 0 Changed: 0 Warnings: 0 + +> SELECT @@LAST_PLAN_FROM_BINDING; +--------------------------+ | @@LAST_PLAN_FROM_BINDING | +--------------------------+ | 1 | +--------------------------+ -1 row in set (0.01 sec) +1 row in set (0.000 sec) +> DELETE t1 FROM t1 JOIN t2 WHERE t1.b = t2.a; +Query OK, 0 rows affected (0.002 sec) + +> SELECT @@LAST_PLAN_FROM_BINDING; ++--------------------------+ +| @@LAST_PLAN_FROM_BINDING | ++--------------------------+ +| 1 | ++--------------------------+ +1 row in set (0.000 sec) + +> SELECT * FROM t1 WHERE t1.a IN (SELECT a FROM t2); +Empty set (0.002 sec) + +> SELECT @@LAST_PLAN_FROM_BINDING; ++--------------------------+ +| @@LAST_PLAN_FROM_BINDING | ++--------------------------+ +| 1 | ++--------------------------+ +1 row in set (0.002 sec) ``` ## MySQL compatibility diff --git a/sql-statements/sql-statement-drop-binding.md b/sql-statements/sql-statement-drop-binding.md index 6413ccf5fc4d2..fdb5d2012ac6f 100644 --- a/sql-statements/sql-statement-drop-binding.md +++ b/sql-statements/sql-statement-drop-binding.md @@ -15,18 +15,26 @@ A `BINDING` can be on either a `GLOBAL` or `SESSION` basis. The default is `SESS ```ebnf+diagram DropBindingStmt ::= 'DROP' GlobalScope 'BINDING' 'FOR' ( BindableStmt ( 'USING' BindableStmt )? -| 'SQL' 'DIGEST' SqlDigest) +| 'SQL' 'DIGEST' StringLiteralOrUserVariableList) GlobalScope ::= ( 'GLOBAL' | 'SESSION' )? BindableStmt ::= ( SelectStmt | UpdateStmt | InsertIntoStmt | ReplaceIntoStmt | DeleteStmt ) + +StringLiteralOrUserVariableList: + (StringLitOrUserVariable | StringLiteralOrUserVariableList ',' StringLitOrUserVariable) + +StringLiteralOrUserVariable: + stringLiteral | UserVariable ``` ## Examples -You can remove a binding according to a SQL statement or `sql_digest`. +You can remove a binding according to a SQL statement or SQL Digest. + +You can use string literals or user variables of string type to specify SQL Digests. You can specify multiple string values, and each string value can also contain multiple digests. In this case, they should be separated by comma. The following example shows how to remove a binding according to a SQL statement. @@ -135,63 +143,61 @@ mysql> SHOW SESSION BINDINGS\G Empty set (0.00 sec) ``` -The following example shows how to remove a binding according to `sql_digest`. +The following example shows how to remove a binding according to SQL Digest. ```sql -mysql> CREATE TABLE t(id INT PRIMARY KEY , a INT, KEY(a)); -Query OK, 0 rows affected (0.06 sec) - -mysql> SELECT /*+ IGNORE_INDEX(t, a) */ * FROM t WHERE a = 1; -Empty set (0.01 sec) - -mysql> SELECT plan_digest FROM INFORMATION_SCHEMA.STATEMENTS_SUMMARY WHERE QUERY_SAMPLE_TEXT = 'SELECT /*+ IGNORE_INDEX(t, a) */ * FROM t WHERE a = 1'; -+------------------------------------------------------------------+ -| plan_digest | -+------------------------------------------------------------------+ -| 4e3159169cc63c14b139a4e7d72eae1759875c9a9581f94bb2079aae961189cb | -+------------------------------------------------------------------+ -1 row in set (0.01 sec) - -mysql> CREATE BINDING FROM HISTORY USING PLAN DIGEST '4e3159169cc63c14b139a4e7d72eae1759875c9a9581f94bb2079aae961189cb'; -Query OK, 0 rows affected (0.02 sec) - -mysql> SELECT * FROM t WHERE a = 1; -Empty set (0.01 sec) - -mysql> SELECT @@LAST_PLAN_FROM_BINDING; -+--------------------------+ -| @@LAST_PLAN_FROM_BINDING | -+--------------------------+ -| 1 | -+--------------------------+ -1 row in set (0.01 sec) - -mysql> SHOW BINDINGS\G -*************************** 1. row *************************** -Original_sql: select * from `test` . `t` where `a` = ? - Bind_sql: SELECT /*+ use_index(@`sel_1` `test`.`t` ) ignore_index(`t` `a`)*/ * FROM `test`.`t` WHERE `a` = 1 - Default_db: test - Status: enabled - Create_time: 2022-12-14 15:26:22.277 - Update_time: 2022-12-14 15:26:22.277 - Charset: utf8mb4 - Collation: utf8mb4_general_ci - Source: history - Sql_digest: 6909a1bbce5f64ade0a532d7058dd77b6ad5d5068aee22a531304280de48349f - Plan_digest: 4e3159169cc63c14b139a4e7d72eae1759875c9a9581f94bb2079aae961189cb -1 row in set (0.02 sec) +CREATE TABLE t1(a INT, b INT, c INT, INDEX ia(a)); +CREATE TABLE t2(a INT, b INT, c INT, INDEX ia(a)); +CREATE GLOBAL BINDING FOR SELECT * FROM t1 WHERE a > 1 USING SELECT * FROM t1 USE INDEX (ia) WHERE a > 1; +CREATE GLOBAL BINDING FOR SELECT * FROM t2 WHERE a < 1 USING SELECT * FROM t2 USE INDEX (ia) WHERE a < 1; +CREATE GLOBAL BINDING FOR SELECT * FROM t1 JOIN t2 ON t1.b = t2.a USING SELECT /*+ HASH_JOIN(t1) */ * FROM t1 JOIN t2 ON t1.b = t2.a; +SHOW GLOBAL BINDINGS; +``` -ERROR: -No query specified +Method 1: +```sql +DROP GLOBAL BINDING FOR SQL DIGEST '31026623c8f22264fe0dfc26f29c69c5c457d6b85960c578ebcf17a967ed7893', '0f38b2e769927ae37981c66f0988c6299b602e03f029e38aa071e656fc321593', '3c8dfc451b0e36afd904cefca5137e68fb051f02964e1958ed60afdadc25f57e'; +SHOW GLOBAL BINDINGS; +``` -mysql> DROP BINDING FOR SQL DIGEST '6909a1bbce5f64ade0a532d7058dd77b6ad5d5068aee22a531304280de48349f'; -Query OK, 0 rows affected (0.00 sec) +Method 2: +```sql +SET @digests='31026623c8f22264fe0dfc26f29c69c5c457d6b85960c578ebcf17a967ed7893, 0f38b2e769927ae37981c66f0988c6299b602e03f029e38aa071e656fc321593, 3c8dfc451b0e36afd904cefca5137e68fb051f02964e1958ed60afdadc25f57e'; +DROP GLOBAL BINDING FOR SQL DIGEST @digests; +SHOW GLOBAL BINDINGS; +``` + +```sql +> CREATE TABLE t1(a INT, b INT, c INT, INDEX ia(a)); +Query OK, 0 rows affected (0.044 sec) + +> CREATE TABLE t2(a INT, b INT, c INT, INDEX ia(a)); +Query OK, 0 rows affected (0.035 sec) + +> CREATE GLOBAL BINDING FOR SELECT * FROM t1 WHERE a > 1 USING SELECT * FROM t1 USE INDEX (ia) WHERE a > 1; +Query OK, 0 rows affected (0.011 sec) + +> CREATE GLOBAL BINDING FOR SELECT * FROM t2 WHERE a < 1 USING SELECT * FROM t2 USE INDEX (ia) WHERE a < 1; +Query OK, 0 rows affected (0.013 sec) + +> CREATE GLOBAL BINDING FOR SELECT * FROM t1 JOIN t2 ON t1.b = t2.a USING SELECT /*+ HASH_JOIN(t1) */ * FROM t1 JOIN t2 ON t1.b = t2.a; +Query OK, 0 rows affected (0.012 sec) + +> SHOW GLOBAL BINDINGS; ++---------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+------------+---------+-------------------------+-------------------------+---------+-----------------+--------+------------------------------------------------------------------+-------------+ +| Original_sql | Bind_sql | Default_db | Status | Create_time | Update_time | Charset | Collation | Source | Sql_digest | Plan_digest | ++---------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+------------+---------+-------------------------+-------------------------+---------+-----------------+--------+------------------------------------------------------------------+-------------+ +| select * from `test` . `t1` join `test` . `t2` on `t1` . `b` = `t2` . `a` | SELECT /*+ HASH_JOIN(`t1`)*/ * FROM `test`.`t1` JOIN `test`.`t2` ON `t1`.`b` = `t2`.`a` | test | enabled | 2024-08-11 04:06:49.953 | 2024-08-11 04:06:49.953 | utf8 | utf8_general_ci | manual | 31026623c8f22264fe0dfc26f29c69c5c457d6b85960c578ebcf17a967ed7893 | | +| select * from `test` . `t2` where `a` < ? | SELECT * FROM `test`.`t2` USE INDEX (`ia`) WHERE `a` < 1 | test | enabled | 2024-08-11 04:06:49.937 | 2024-08-11 04:06:49.937 | utf8 | utf8_general_ci | manual | 0f38b2e769927ae37981c66f0988c6299b602e03f029e38aa071e656fc321593 | | +| select * from `test` . `t1` where `a` > ? | SELECT * FROM `test`.`t1` USE INDEX (`ia`) WHERE `a` > 1 | test | enabled | 2024-08-11 04:06:49.924 | 2024-08-11 04:06:49.924 | utf8 | utf8_general_ci | manual | 3c8dfc451b0e36afd904cefca5137e68fb051f02964e1958ed60afdadc25f57e | | ++---------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+------------+---------+-------------------------+-------------------------+---------+-----------------+--------+------------------------------------------------------------------+-------------+ +3 rows in set (0.001 sec) -mysql> SHOW BINDINGS\G -Empty set (0.01 sec) +> DROP GLOBAL BINDING FOR SQL DIGEST '31026623c8f22264fe0dfc26f29c69c5c457d6b85960c578ebcf17a967ed7893', '0f38b2e769927ae37981c66f0988c6299b602e03f029e38aa071e656fc321593', '3c8dfc451b0e36afd904cefca5137e68fb051f02964e1958ed60afdadc25f57e'; +Query OK, 3 rows affected (0.019 sec) -ERROR: -No query specified +> SHOW GLOBAL BINDINGS; +Empty set (0.002 sec) ``` ## MySQL compatibility