Skip to content

Commit d82b4b3

Browse files
authored
Spm fix hint issue (pingcap#19740)
1 parent b89d270 commit d82b4b3

File tree

1 file changed

+25
-31
lines changed

1 file changed

+25
-31
lines changed

sql-plan-management.md

+25-31
Original file line numberDiff line numberDiff line change
@@ -43,50 +43,44 @@ CREATE [GLOBAL | SESSION] BINDING [FOR BindableStmt] USING BindableStmt;
4343
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. The following is an example:
4444

4545
```sql
46-
CREATE GLOBAL BINDING USING SELECT /*+ use_index(t1, idx_a) */ * FROM t1;
47-
CREATE GLOBAL BINDING FOR SELECT * FROM t1 USING SELECT /*+ use_index(t1, idx_a) */ * FROM t1;
46+
CREATE GLOBAL BINDING USING SELECT /*+ use_index(orders, orders_book_id_idx) */ * FROM orders;
47+
CREATE GLOBAL BINDING FOR SELECT * FROM orders USING SELECT /*+ use_index(orders, orders_book_id_idx) */ * FROM orders;
4848
```
4949

5050
> **Note:**
5151
>
5252
> 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.
5353
54-
Specifically, two types of these statements cannot be bound to execution plans due to syntax conflicts. See the following examples:
54+
Specifically, two types of these statements cannot be bound to execution plans due to syntax conflicts. A syntax error will be reported during binding creation. See the following examples:
5555

5656
```sql
5757
-- Type one: Statements that get the Cartesian product by using the `JOIN` keyword and not specifying the associated columns with the `USING` keyword.
5858
CREATE GLOBAL BINDING for
59-
SELECT * FROM t t1 JOIN t t2
59+
SELECT * FROM orders o1 JOIN orders o2
6060
USING
61-
SELECT * FROM t t1 JOIN t t2;
61+
SELECT * FROM orders o1 JOIN orders o2;
6262

6363
-- Type two: `DELETE` statements that contain the `USING` keyword.
6464
CREATE GLOBAL BINDING for
65-
DELETE FROM t1 USING t1 JOIN t2 ON t1.a = t2.a
65+
DELETE FROM users USING users JOIN orders ON users.id = orders.user_id
6666
USING
67-
DELETE FROM t1 USING t1 JOIN t2 ON t1.a = t2.a;
67+
DELETE FROM users USING users JOIN orders ON users.id = orders.user_id;
6868
```
6969

7070
You can bypass syntax conflicts by using equivalent statements. For example, you can rewrite the above statements in the following ways:
7171

7272
```sql
73-
-- First rewrite of type one statements: Add a `USING` clause for the `JOIN` keyword.
73+
-- Rewrite of type one statements: Delete the `JOIN` keyword. Replace it with a comma.
7474
CREATE GLOBAL BINDING for
75-
SELECT * FROM t t1 JOIN t t2 USING (a)
75+
SELECT * FROM orders o1, orders o2
7676
USING
77-
SELECT * FROM t t1 JOIN t t2 USING (a);
77+
SELECT * FROM orders o1, orders o2;
7878

79-
-- Second rewrite of type one statements: Delete the `JOIN` keyword.
79+
-- Rewrite of type two statements: Remove the `USING` keyword from the `DELETE` statement.
8080
CREATE GLOBAL BINDING for
81-
SELECT * FROM t t1, t t2
81+
DELETE users FROM users JOIN orders ON users.id = orders.user_id
8282
USING
83-
SELECT * FROM t t1, t t2;
84-
85-
-- Rewrite of type two statements: Remove the `USING` keyword from the `delete` statement.
86-
CREATE GLOBAL BINDING for
87-
DELETE t1 FROM t1 JOIN t2 ON t1.a = t2.a
88-
using
89-
DELETE t1 FROM t1 JOIN t2 ON t1.a = t2.a;
83+
DELETE users FROM users JOIN orders ON users.id = orders.user_id;
9084
```
9185

9286
> **Note:**
@@ -98,25 +92,25 @@ Here are two examples:
9892
```sql
9993
-- The hint takes effect in the following statement.
10094
CREATE GLOBAL BINDING for
101-
INSERT INTO t1 SELECT * FROM t2 WHERE a > 1 AND b = 1
102-
using
103-
INSERT INTO t1 SELECT /*+ use_index(@sel_1 t2, idx_a) */ * FROM t2 WHERE a > 1 AND b = 1;
95+
INSERT INTO orders SELECT * FROM pre_orders WHERE status = 'VALID' AND created <= (NOW() - INTERVAL 1 HOUR)
96+
USING
97+
INSERT INTO orders SELECT /*+ use_index(@sel_1 pre_orders, idx_created) */ * FROM pre_orders WHERE status = 'VALID' AND created <= (NOW() - INTERVAL 1 HOUR);
10498

10599
-- The hint cannot take effect in the following statement.
106100
CREATE GLOBAL BINDING for
107-
INSERT INTO t1 SELECT * FROM t2 WHERE a > 1 AND b = 1
108-
using
109-
INSERT /*+ use_index(@sel_1 t2, idx_a) */ INTO t1 SELECT * FROM t2 WHERE a > 1 AND b = 1;
101+
INSERT INTO orders SELECT * FROM pre_orders WHERE status = 'VALID' AND created <= (NOW() - INTERVAL 1 HOUR)
102+
USING
103+
INSERT /*+ use_index(@sel_1 pre_orders, idx_created) */ INTO orders SELECT * FROM pre_orders WHERE status = 'VALID' AND created <= (NOW() - INTERVAL 1 HOUR);
110104
```
111105

112106
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.
113107

114108
`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:
115109

116110
```sql
117-
SELECT * FROM t WHERE a > 1
111+
SELECT * FROM users WHERE balance > 100
118112
-- After normalization, the above statement is as follows:
119-
SELECT * FROM test . t WHERE a > ?
113+
SELECT * FROM bookshop . users WHERE balance > ?
120114
```
121115

122116
> **Note:**
@@ -126,11 +120,11 @@ SELECT * FROM test . t WHERE a > ?
126120
> For example:
127121
>
128122
> ```sql
129-
> SELECT * FROM t WHERE a IN (1)
130-
> SELECT * FROM t WHERE a IN (1,2,3)
123+
> SELECT * FROM books WHERE type IN ('Novel')
124+
> SELECT * FROM books WHERE type IN ('Novel','Life','Education')
131125
> -- After normalization, the above statements are as follows:
132-
> SELECT * FROM test . t WHERE a IN ( ... )
133-
> SELECT * FROM test . t WHERE a IN ( ... )
126+
> SELECT * FROM bookshop . books WHERE type IN ( ... )
127+
> SELECT * FROM bookshop . books WHERE type IN ( ... )
134128
> ```
135129
>
136130
> After normalization, `IN` predicates of different lengths are recognized as the same statement, so you only need to create one binding that applies to all these predicates.

0 commit comments

Comments
 (0)