The execution plan of SQL statements in the production environment constantly changes. Therefore, databases can be unstable. PolarDB for MySQL provides the statement outline feature that uses optimizer hints and index hints to ensure the stability of execution plans. PolarDB for MySQL also provides the DBMS_OUTLN
package. You can use the package to enable the statement outline feature. This topic describes how to use and manage the statement outline feature.
Prerequisites
Your cluster is a PolarDB cluster that runs one of the following versions:
PolarDB for MySQL 5.6 whose revision version is 5.6.1.0.36 or later.
PolarDB for MySQL 5.7 whose revision version is 5.7.1.0.2 or later.
PolarDB for MySQL 8.0.1 whose revision version is 8.0.1.1.1 or later.
PolarDB for MySQL 8.0.2.
For information about how to check the version of a cluster, see Query the engine version.
Hints
The statement outline feature supports the following types of hints provided by MySQL 8.0:
Optimizer Hints
Optimizer hints are classified into table-level optimizer hints, index-level optimizer hints, and join-order optimizer hints based on applicable scopes and hint objects. For more information, see Optimizer Hints.
NoteOptimizer hints are not supported in PolarDB for MySQL 5.6 clusters.
Index Hints
Index hints are classified based on types and scopes. For more information, see Index Hints.
Parameters
Log on to the PolarDB console. On the parameter configuration page, you can configure the opt_outline_enabled parameter described in the following table to enable or disable the statement outline feature. For more information, see Specify cluster and node parameters.
Parameter | Level | Description |
loose_opt_outline_enabled | Global | Specifies whether to enable the statement outline feature. Valid values:
|
Outline tables
PolarDB uses a system table named outline
to store hints. The system automatically creates the table on startup. The following statement is used to create the system table:
CREATE TABLE `mysql`.`outline` (
`Id` bigint(20) NOT NULL AUTO_INCREMENT,
`Schema_name` varchar(64) COLLATE utf8_bin DEFAULT NULL,
`Digest` varchar(64) COLLATE utf8_bin NOT NULL,
`Digest_text` longtext COLLATE utf8_bin,
`Type` enum('IGNORE INDEX','USE INDEX','FORCE INDEX','OPTIMIZER') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`Scope` enum('','FOR JOIN','FOR ORDER BY','FOR GROUP BY') CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '',
`State` enum('N','Y') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'Y',
`Position` bigint(20) NOT NULL,
`Hint` text COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`Id`)
) /*!50100 TABLESPACE `mysql` */ ENGINE=InnoDB
DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0 COMMENT='Statement outline'
The following table describes the parameters in the statement.
Parameter | Description |
Id | The ID of the outline table. |
Schema_name | The name of the database that belongs to the account. |
Digest | The 64-byte statement digest hash value that is calculated based on the value of the Digest_text parameter. For more information, see STATEMENT_DIGEST(). |
Digest_text | The digest of the SQL statement. |
Type |
|
Scope | This parameter is required only for index hints. Valid values:
Note An empty string indicates index hints of all types. |
State | Specifies whether the rule is enabled. Valid values:
|
Position |
|
Hint |
|
If the
Schema_name
parameter is specified, theSchema_name
andDigest
values of the SQL statement must be the same as theSchema_name
andDigest
values in the statement outline rule. Otherwise, the statement outline rule does not take effect.If the
Schema_name
parameter is left empty, theDigest
value of the SQL statement must be the same as theDigest
value in the statement outline rule. Otherwise, the statement outline rule does not take effect.
Manage statement outline rules
You can manage statement outline rules only on the primary node. After the operation is complete, the changes are automatically synchronized to other nodes.
PolarDB provides six local rules in the DBMS_OUTLN package. You can use the rules to manage statement outline rules.
add_optimizer_outline: adds optimizer hints.
Syntax
Syntax 1:
dbms_outln.add_optimizer_outline('<Schema_name>','<Digest>','<query_block>','<hint>','<query>');
Syntax 2: This syntax lacks the Digest and query_block parameters present in Syntax 1. It leaves the Digest parameter unconfigured, and uses a default value of 1 for the query_block parameter.
dbms_outln.add_optimizer_outline('<Schema_name>','<hint>','<query>');
NoteThe add_optimizer_outline rule is not supported in PolarDB for MySQL 5.6 clusters.
When you use Syntax 1, you can specify Digest or query in the statement. If you enter a query statement for the query parameter, DBMS_OUTLN calculates the values of the Digest and Digest_text parameters.
If a quotation mark is required for a field in a query statement, add a single quotation mark (") to the field and enclose the query statement with a pair of double quotation marks ("").
Examples
The
Schema_name
andDigest
values of a query are the same as the corresponding values in the statement outline rule. Example:CALL dbms_outln.add_optimizer_outline('outline_db', '', 1, '/*+ MAX_EXECUTION_TIME(1000) */', 'SELECT * FROM t1 WHERE id = 1');
The preceding statement is equivalent to the following statement:
CALL dbms_outln.add_optimizer_outline('outline_db', '/*+ MAX_EXECUTION_TIME(1000) */', 'SELECT * FROM t1 WHERE id = 1');
The preceding statement is also equivalent to the following statement:
CALL dbms_outln.add_optimizer_outline('outline_db', '36bebc61fce7e32b93926aec3fdd790dad5d895107e2d8d3848d1c60b74bcde6', 1, '/*+ MAX_EXECUTION_TIME(1000) */', '');
36bebc61fce7e32b93926aec3fdd790dad5d895107e2d8d3848d1c60b74bcde6
is theDigest
value from theSELECT * FROM t1 WHERE id = 1
statement. Therefore, the two statements have the same results.The
Digest
value of the SQL statement is the same as the corresponding value in the statement outline rule. Example:CALL dbms_outln.add_optimizer_outline('', '', 1, '/*+ MAX_EXECUTION_TIME(1000) */', 'SELECT * FROM t1 WHERE id = 1');
add_index_outline: adds index hints.
Syntax
dbms_outln.add_index_outline('<Schema_name>','<Digest>',<Position>,'<Type>','<Hint>','<Scope>','<Query>');
NoteYou can specify Digest or Query in the statement. If you enter a query statement for the Query parameter, DBMS_OUTLN calculates the values of the Digest and Digest_text parameters.
Examples
The
Schema_name
andDigest
values of a query are the same as the corresponding values in the statement outline rule. Example:CALL dbms_outln.add_index_outline('outline_db', '', 1, 'USE INDEX', 'ind_1', '', "SELECT * FROM t1 WHERE t1.col1 =1 AND t1.col2 ='xpchild'");
The preceding statement is equivalent to the following statement:
CALL dbms_outln.add_index_outline('outline_db', 'b4369611be7ab2d27c85897632576a04bc08f50b928a1d735b62d0a140628c4c', 1, 'USE INDEX', 'ind_1', '', "");
b4369611be7ab2d27c85897632576a04bc08f50b928a1d735b62d0a140628c4c
is theDigest
value from theSELECT * FROM t1 WHERE t1.col1 =1 AND t1.col2 ='xpchild
statement. Therefore, the two statements have the same results.The
Digest
value of the SQL statement is the same as the corresponding value in the statement outline rule. Example:CALL dbms_outln.add_index_outline('', '', 1, 'USE INDEX', 'ind_1', '', "SELECT * FROM t1 WHERE t1.col1 =1 AND t1.col2 ='xpchild'");
preview_outline: checks how a statement outline rule matches a query, which can be used for manual verification.
Syntax
dbms_outln.preview_outline('<Schema_name>','<Query>');
Example
CALL dbms_outln.preview_outline('outline_db', "SELECT * FROM t1 WHERE t1.col1 =1 AND t1.col2 ='xpchild'"); +------------+------------------------------------------------------------------+------------+------------+-------+---------------------+ | SCHEMA | DIGEST | BLOCK_TYPE | BLOCK_NAME | BLOCK | HINT | +------------+------------------------------------------------------------------+------------+------------+-------+---------------------+ | outline_db | b4369611be7ab2d27c85897632576a04bc08f50b928a1d735b62d0a140628c4c | TABLE | t1 | 1 | USE INDEX (`ind_1`) | +------------+------------------------------------------------------------------+------------+------------+-------+---------------------+ 1 row in set (0.00 sec)
show_outline: displays the in-memory hits of a statement outline rule.
Syntax
dbms_outln.show_outline();
Example
CALL dbms_outln.show_outline(); +------+------------+------------------------------------------------------------------+-----------+-------+------+-------------------------------------------------------+------+----------+-------------------------------------------------------------------------------------+ | ID | SCHEMA | DIGEST | TYPE | SCOPE | POS | HINT | HIT | OVERFLOW | DIGEST_TEXT | +------+------------+------------------------------------------------------------------+-----------+-------+------+-------------------------------------------------------+------+----------+-------------------------------------------------------------------------------------+ | 33 | outline_db | 36bebc61fce7e32b93926aec3fdd790dad5d895107e2d8d3848d1c60b74bcde6 | OPTIMIZER | | 1 | /*+ SET_VAR(foreign_key_checks=OFF) */ | 1 | 0 | SELECT * FROM `t1` WHERE `id` = ? | | 32 | outline_db | 36bebc61fce7e32b93926aec3fdd790dad5d895107e2d8d3848d1c60b74bcde6 | OPTIMIZER | | 1 | /*+ MAX_EXECUTION_TIME(1000) */ | 2 | 0 | SELECT * FROM `t1` WHERE `id` = ? | | 34 | outline_db | d4dcef634a4a664518e5fb8a21c6ce9b79fccb44b773e86431eb67840975b649 | OPTIMIZER | | 1 | /*+ BNL(t1,t2) */ | 1 | 0 | SELECT `t1` . `id` , `t2` . `id` FROM `t1` , `t2` | | 35 | outline_db | 5a726a609b6fbfb76bb8f9d2a24af913a2b9d07f015f2ee1f6f2d12dfad72e6f | OPTIMIZER | | 2 | /*+ QB_NAME(subq1) */ | 2 | 0 | SELECT * FROM `t1` WHERE `t1` . `col1` IN ( SELECT `col1` FROM `t2` ) | | 36 | outline_db | 5a726a609b6fbfb76bb8f9d2a24af913a2b9d07f015f2ee1f6f2d12dfad72e6f | OPTIMIZER | | 1 | /*+ SEMIJOIN(@subq1 MATERIALIZATION, DUPSWEEDOUT) */ | 2 | 0 | SELECT * FROM `t1` WHERE `t1` . `col1` IN ( SELECT `col1` FROM `t2` ) | | 30 | outline_db | b4369611be7ab2d27c85897632576a04bc08f50b928a1d735b62d0a140628c4c | USE INDEX | | 1 | ind_1 | 3 | 0 | SELECT * FROM `t1` WHERE `t1` . `col1` = ? AND `t1` . `col2` = ? | | 31 | outline_db | 33c71541754093f78a1f2108795cfb45f8b15ec5d6bff76884f4461fb7f33419 | USE INDEX | | 2 | ind_2 | 1 | 0 | SELECT * FROM `t1` , `t2` WHERE `t1` . `col1` = `t2` . `col1` AND `t2` . `col2` = ? | +------+------------+------------------------------------------------------------------+-----------+-------+------+-------------------------------------------------------+------+----------+-------------------------------------------------------------------------------------+ 7 rows in set (0.00 sec)
HIT
indicates the number of in-memory hits of the statement outline rule.OVERFLOW
indicates the number of times that the query block or table failed to be found.del_outline: deletes a statement outline rule from the memory or table.
Syntax
dbms_outln.del_outline(<Id>);
Example
CALL dbms_outln.del_outline(32);
NoteIf the statement outline rule that you want to delete does not exist, an error is returned. You can execute the
SHOW WARNINGS;
statement to view the error message.CALL dbms_outln.del_outline(1000); Query OK, 0 rows affected, 2 warnings (0.00 sec) SHOW WARNINGS; +---------+------+----------------------------------------------+ | Level | Code | Message | +---------+------+----------------------------------------------+ | Warning | 7521 | Statement outline 1000 is not found in table | | Warning | 7521 | Statement outline 1000 is not found in cache | +---------+------+----------------------------------------------+ 2 rows in set (0.00 sec)
flush_outline: re-validates a statement outline rule if you update the statement outline rule in the
outline
table.Syntax
dbms_outln.flush_outline();
Example
UPDATE mysql.outline SET Position = 1 WHERE Id = 18; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 CALL dbms_outln.flush_outline(); Query OK, 0 rows affected (0.01 sec)
Test the feature
You can check whether the statement outline rule takes effect by using one of the following methods:
Execute the preview_outline statement.
CALL dbms_outln.preview_outline('outline_db', "SELECT * FROM t1 WHERE t1.col1 =1 AND t1.col2 ='xpchild'"); +------------+------------------------------------------------------------------+------------+------------+-------+---------------------+ | SCHEMA | DIGEST | BLOCK_TYPE | BLOCK_NAME | BLOCK | HINT | +------------+------------------------------------------------------------------+------------+------------+-------+---------------------+ | outline_db | b4369611be7ab2d27c85897632576a04bc08f50b928a1d735b62d0a140628c4c | TABLE | t1 | 1 | USE INDEX (`ind_1`) | +------------+------------------------------------------------------------------+------------+------------+-------+---------------------+ 1 row in set (0.01 sec)
Execute the EXPLAIN statement.
EXPLAIN SELECT * FROM t1 WHERE t1.col1 =1 AND t1.col2 ='xpchild'; +----+-------------+-------+------------+------+---------------+-------+---------+-------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+-------+---------+-------+------+----------+-------------+ | 1 | SIMPLE | t1 | NULL | ref | ind_1 | ind_1 | 5 | const | 1 | 100.00 | Using where | +----+-------------+-------+------------+------+---------------+-------+---------+-------+------+----------+-------------+ 1 row in set, 1 warning (0.00 sec) SHOW WARNINGS; +-------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Level | Code | Message | +-------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Note | 1003 | /* select#1 */ select `outline_db`.`t1`.`id` AS `id`,`outline_db`.`t1`.`col1` AS `col1`,`outline_db`.`t1`.`col2` AS `col2` from `outline_db`.`t1` USE INDEX (`ind_1`) where ((`outline_db`.`t1`.`col1` = 1) and (`outline_db`.`t1`.`col2` = 'xpchild')) | +-------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)