The execution plan of SQL statements in the production environment constantly changes. Therefore, databases can be unstable. PolarDB provides the statement outline feature that uses optimizer hints and index hints to ensure stable execution plans. PolarDB also provides the DBMS_OUTLN
package to use the statement outline feature. This topic describes how to use and manage the statement outline feature.
Prerequisites
The version of the PolarDB cluster must meet one of the following requirements:
- A PolarDB for MySQL 5.6 cluster whose revision version is 5.6.1.0.36 or later.
- A PolarDB for MySQL 5.7 cluster whose revision version is 5.7.1.0.2 or later.
- A PolarDB for MySQL 8.0 cluster whose revision version is 8.0.1.1.1 or later.
For information about how to view the version of your cluster, see Query the engine version.
Hints
The statement outline feature supports the following types of hints provided by MySQL 8.0.
- Optimizer Hints
Based on applicable scopes and hint objects, optimizer hints are classified into table-level optimizer hints, index-level optimizer hints, and join-order optimizer hints. For more information, see Optimizer Hints.
Note Optimizer hints are not supported on PolarDB for MySQL 5.6 clusters. - Index Hints
Index hints are classified based on the types and scopes. For more information, see Index Hints.
The outline table
PolarDB uses a system table named outline
to store hints. The system automatically creates the table when the system is started. The following statement is used to create this 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.
Parameter | Description |
---|---|
Id | The ID of the outline table. |
Schema_name | The name of the database. |
Digest | The 64-byte statement digest hash value that is calculated by Digest_text. For more information, see STATEMENT_DIGEST(). |
Digest_text | The normalized statement 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. Default value: Y. Valid values:
|
Position |
|
Hint |
|
Manage statement outline rules
- If the
Schema_name
parameter is not empty, theSchema_name
andDigest
values of the SQL statement must be consistent with theSchema_name
andDigest
values in the statement outline rule. Otherwise, the statement outline rule does not take effect. - If the
Schema_name
parameter is empty, theDigest
value of the SQL statement must be consistent with theDigest
value in the statement outline rule.
- add_optimizer_outline: adds optimizer hints. SyntaxExamples
dbms_outln.add_optimizer_outline('<Schema_name>','<Digest>','<query_block>','<hint>','<query>');
Note- add_optimizer_outline is not supported on PolarDB for MySQL 5.6 clusters.
- You can enter the Digest or Query in the statement. If you enter a query statement for Query, DBMS_OUTLN calculates the values of Digest and Digest_text.
- The
Schema_name
andDigest
values are consistent. Example:
The preceding statement is equivalent to the following statement:CALL dbms_outln.add_optimizer_outline("outline_db", '', 1, '/*+ MAX_EXECUTION_TIME(1000) */', "SELECT * FROM t1 WHERE id = 1");
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, so the two statements have the same results. - The
Digest
value is consistent. Example:CALL dbms_outln.add_optimizer_outline("", '', 1, '/*+ MAX_EXECUTION_TIME(1000) */', "SELECT * FROM t1 WHERE id = 1");
- add_index_outline: adds index hints. SyntaxExamples
dbms_outln.add_index_outline('<Schema_name>','<Digest>',<Position>,'<Type>','<Hint>','<Scope>','<Query>');
Note You can enter the Digest or Query in the statement. If you enter a query statement for Query, DBMS_OUTLN calculates the values of Digest and Digest_text.- The
Schema_name
andDigest
values are consistent. Example:
The preceding statement is equivalent to the following statement:CALL dbms_outln.add_index_outline('outline_db', '', 1, 'USE INDEX', 'ind_1', '', "SELECT * FROM t1 WHERE t1.col1 =1 AND t1.col2 ='xpchild'");
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, so the two statements have the same results. - The
Digest
value is consistent. Example:CALL dbms_outln.add_index_outline('', '', 1, 'USE INDEX', 'ind_1', '', "SELECT * FROM t1 WHERE t1.col1 =1 AND t1.col2 ='xpchild'");
- The
- preview_outline: checks the result of a statement outline rule, which can be used for manual verification. Syntax
Examplesdbms_outln.preview_outline('<Schema_name>','<Query>');
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: views the in-memory hits of a statement outline rule. Syntax
Examplesdbms_outln.show_outline();
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 memory hits of the statement outline rule.OVERFLOW
indicates the number of failure to find the query block or table. - del_outline: deletes a statement outline rule from the memory or table, Syntax
Examplesdbms_outln.del_outline(<Id>);
CALL dbms_outln.del_outline(32);
Note If the statement outline rule that you want to delete does not exist, an error is returned. You can execute theSHOW 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: validates a statement outline rule again if you update the statement outline rule in the
outline
table.Syntax
Examplesdbms_outln.flush_outline();
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
- 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)