You need to enable JavaScript to run this app.
导航
Statement outline for MySQL 8.0
最近更新时间:2025.04.22 17:22:45首次发布时间:2025.04.22 17:22:45
我的收藏
有用
有用
无用
无用

背景信息

Statement outline

实例运行过程中,一些 SQL 的执行计划可能会发生非预期的变化,造成稳定性风险。
例如:

  1. 在线业务使用 order by limit n 的用法,在 n 值比较小的时候频繁出现执行计划变动影响性能,

  2. 数据量变化时,统计数据也会发生改变。这些变化可能引起优化器的代价选择出现错误判断,选择了非最优的索引。

临时解决办法如实例通过调整 optimizer_switch 参数,或者通过修改业务 SQL 添加 hint 来绑定执行计划,对业务都不够友好。而 Statement outline 功能可将 SQL 的执行计划与 SQL 查询模板绑定,用户无需修改 SQL 即可将查询计划固化,避免出现上述风险。

术语说明

缩略语英文全名中文解释

Outline

Statement outline

执行计划固化,用于解决生产环境中 SQL 语句的执行计划经常会发生改变,而导致数据库不稳定的问题。

PackageNative package procedure framework原生工具包,是一组预定义的存储过程(stored procedure)的逻辑集合,方便使用一个领域的相关存储过程。
DigestSQL DigestSQL 指纹,在 MySQL 8.0 中默认使用 SHA256 值,每条模板有唯一的值。
Digest TextSQL Digest TextSQL 模板,将 SQL 参数去除后的 SQL 语句。

相关参数

参数名级别取值范围默认值描述
loose_outline_enabledGLOBAL[ONOFF]ON

说明

该参数为非开放的可修改参数,如需修改请提交工单联系技术支持。

前提条件

已创建 MySQL 8.0 实例,且实例的内核小版本为 20250215 或更新版本。关于创建实例和查看实例内核小版本的相关信息,请参见创建实例

说明

如您的实例是在 2025 年 02 月 15 日之后创建,则自动使用 20250215 或更新的内核小版本。如您的实例是在 2025 年 02 月 15 日之前创建,则会使用 20250215 之前的内核小版本。此时,您可通过手动方式升级实例的内核小版本,详细信息,请参见手动升级实例内核小版本

Hint

MySQL 通过 hint 提供了语句维度的优化器控制,通过将 hint 添加至 SQL 语句,即可对 SQL 查询器的决策进行干预:

SELECT /*+ NO_RANGE_OPTIMIZATION(t3 PRIMARY, f2_idx) */ f1 FROM t3 WHERE f1 > 30 AND f1 < 33;
SELECT /*+ BKA(t1) NO_BKA(t2) */ * FROM t1 INNER JOIN t2 WHERE ...;
SELECT /*+ NO_ICP(t1, t2) */ * FROM t1 INNER JOIN t2 WHERE ...;
SELECT /*+ SEMIJOIN(FIRSTMATCH, LOOSESCAN) */ * FROM t1 ...;
EXPLAIN SELECT /*+ NO_ICP(t1) */ * FROM t1 WHERE ...;
SELECT /*+ MERGE(dt) */ * FROM (SELECT * FROM t1) AS dt;
INSERT /*+ SET_VAR(foreign_key_checks=OFF) */ INTO t2 VALUES(2);

Statement outline 功能支持把两类 Hint 绑定至 SQL 模板中,从而达到查询计划固化的效果。支持的 Hint 类型与 MySQL 8.0 一致:

SQL 语法接口

云数据库 MySQL 版的 8.0 内置了 Outline 相关的原生存储过程(Native Package)工具包,用户可通过调用 dbms_outline 相关接口进行 Outline 的操作。

insert_optimizer_outline

  • 描述:增加 Optimizer Hints。

  • 语法:

    CALL dbms_outline.insert_optimizer_outline('<Schema_name>','<Digest>','<Query_block>','<Hint>','<Query>');
    
  • 参数说明:

    参数说明

    Schema_name

    数据库名称。

    说明

    通过添加空<Schema_name>: '',可将 Outline 应用于所有匹配的 Schema。

    Digest查询对应的 SQL 指纹。
    Query_Block需要应用该 Hint 的关键字(如SELECTUPDATE等)编号,从1开始
    HintHint 表示完整的 Hint 字符串,例如 /*+ NO_ICP(t1, t2) */
    Query需要添加 Statement outline 的原始 SQL 语句。

说明

- Digest 和 Query(原始 SQL语句)可以任选其一。如果填写 Query,`dbms_outline` 会计算指纹(Digest)和 SQL 模板(Digest\_text)。
- Query 语句中需要使用引号时,需要在 query 语句中给需要添加引号的部分添加单引号,并使用双引号包围 query。
  • 示例:

    CALL dbms_outline.insert_optimizer_outline('outline_db', '', 1, '/*+ MAX_EXECUTION_TIME(1000) */', 'SELECT * FROM t1 WHERE id = 1');
    

insert_index_outline

  • 描述:增加 Index Hints。

  • 语法:

    CALL dbms_outline.insert_index_outline('<Schema_name>','<Digest>','<Position>','<Type>','<Hint>','<Scope>','<Query>');
    
  • 参数说明

    参数说明

    Schema_name

    数据库名称。

    说明

    通过添加空<Schema_name>: '',可将 Outline 应用于所有匹配的 Schema。

    Digest查询对应的SQL 指纹。
    Position需要应用该 Hint 的表的位置,从1开始
    TypeIndex Hint 类型。取值为 USE INDEXFORCE INDEXIGNORE INDEX
    Hint索引名字的列表, 例如 idx_1,idx_2。

    Scope

    分为如下三类:

    • FOR GROUP BY

    • FOR ORDER BY

    • FOR JOIN

    空串表示所有类型的 Index Hints。

    Query需要添加 Statement outline 的原始 SQL 语句。

    说明

    • Digest 和 Query(原始 SQL 语句)可以任选其一。如果填写 Query,dbms_outline 会计算指纹(Digest)和 SQL 模板(Digest_text)。
    • Query 语句中需要使用引号时,需要在 query 语句中给需要添加引号的部分添加单引号,并使用双引号包围 query。

  • 示例:

    -- 使用原始 SQL 语句
    CALL dbms_outline.insert_index_outline('outline_db', '', 1, 'FORCE INDEX', 'idx_1', '',"SELECT * FROM t1 WHERE t1.col1 = 1 AND t1.col2 = 'mytest'");
    
    -- 使用 SQL 指纹
    CALL dbms_outline.insert_index_outline('outline_db', 'b4369611be7ab2d27c85897632576a04bc08f50b928a1d735b62d0a140628c4c', 1, 'USE INDEX', 'idx_1', '', "");
    

check_outline

  • 描述:验证 SQL 语句 Statement outline 的生效情况,如果找到了匹配值,该 SQL 模板将会应用指定的 Hint。

  • 语法:

    CALL dbms_outline.check_outline('<Schema_name>', '<Query>');
    
  • 参数说明:

    参数说明

    Schema_name

    数据库名称。

    说明

    通过添加空 <Schema_name>: '',可将 Outline 应用于所有匹配的 Schema。

    Query需要添加 Statement outline 的原始 SQL 语句。
  • 示例:

    CALL dbms_outline.check_outline('outline_db', "SELECT * FROM t1 WHERE t1.col1 =1 AND t1.col2 ='mytest'");
    +------------+------------------------------------------------------------------+------------+------------+-------+---------------------+
    | SCHEMA     | DIGEST                                                          | BLOCK_TYPE | BLOCK_NAME | BLOCK | HINT                |
    +------------+------------------------------------------------------------------+------------+------------+-------+---------------------+
    | outline_db | b4369611be7ab2d27c85897632576a04bc08f50b928a1d735b62d0a140628c4c | TABLE      | t1         |     1 | USE INDEX (`idx_1`) |
    +------------+------------------------------------------------------------------+------------+------------+-------+---------------------+
    
  • Explain:

通过 EXPLAIN 语句也可以查看 Outline 是否生效。

explain select * from t1 where t1.col1 =1 and t1.col2 ='mytest';
+----+-------------+-------+------------+------+---------------+-------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key   | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+-------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | t1    | NULL       | ref  | idx_1         | idx_1 | 5       | const |    1 |   100.00 | Using where |
+----+-------------+-------+------------+------+---------------+-------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

mysql> 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 (`idx_1`) where ((`outline_db`.`t1`.`col1` = 1) and (`outline_db`.`t1`.`col2` = 'mytest')) |
+-------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

display_outline

  • 描述:查看系统中保存 Statement outline 以及生效情况。

  • 语法:

    CALL dbms_outline.display_outline();
    
  • 示例:

    CALL dbms_outline.display_outline();
    +------+------------+------------------------------------------------------------------+-----------+-------+------+--------------------+------+----------+-----------------------------------------------------------------------------------------------------------------+
    | ID   | SCHEMA     | DIGEST                                                           | TYPE      | SCOPE | POS  | HINT               | HIT  | OVERFLOW | DIGEST_TEXT                                                                                                     |
    +------+------------+------------------------------------------------------------------+-----------+-------+------+--------------------+------+----------+-----------------------------------------------------------------------------------------------------------------+
    |    1 | outline_db | ab234071d1d3af13a775f45b532639203e1aa8c3ec63b289a75b9fb862c61c4c | USE INDEX |       |    1 | idx_1              |    0 |        0 | SELECT * FROM `t1` WHERE `t1` . `id` = ? UNION SELECT * FROM `t1` WHERE `t1` . `col1` = ? AND `t1` . `col2` = ? |
    |    2 | outline_db | ab234071d1d3af13a775f45b532639203e1aa8c3ec63b289a75b9fb862c61c4c | OPTIMIZER |       |    2 | /*+ QB_NAME(q2) */ |    0 |        0 | SELECT * FROM `t1` WHERE `t1` . `id` = ? UNION SELECT * FROM `t1` WHERE `t1` . `col1` = ? AND `t1` . `col2` = ? |
    +------+------------+------------------------------------------------------------------+-----------+-------+------+--------------------+------+----------+-----------------------------------------------------------------------------------------------------------------+
    

说明

  • HIT 表示该 Statement outline 命中的次数,
  • OVERFLOW 表示该 Statement outline 只匹配了 schema 和 digest 而没有找到 Query Block 或相应的表的次数。

delete_outline

  • 描述:删除内存和表中的某一条 Statement outline。

  • 语法:

    CALL dbms_outline.delete_outline(<Id>);
    
  • 参数说明:

    参数说明
    IdOutline ID。
  • 示例:

    CALL dbms_outline.delete_outline(2);
    

    如果删除的 Outline 不存在,会返回警告,使用 SHOW WARNINGS 查看警告内容。

    --删除不存在的 outline
    CALL dbms_outline.delete_outline(999999);
    Query OK, 0 rows affected, 2 warnings (0.00 sec)
    
    SHOW WARNINGS;
    +---------+------+------------------------------------------------+
    | Level   | Code | Message                                        |
    +---------+------+------------------------------------------------+
    | Warning | 7521 | Statement outline 999999 is not found in table |
    | Warning | 7521 | Statement outline 999999 is not found in cache |
    +---------+------+------------------------------------------------+
    2 rows in set (0.00 sec)
    

常见场景

Index Hint

指定使用 t1 表的 idx_1 索引

CALL dbms_outline.insert_index_outline('outline_db', '', 1, 'USE INDEX', 'idx_1', '',
    "select * from t1 where t1.col1 =1 and t1.col2 ='mytest'");

Optimizer Hint

使用 Nested-Loop join

  • 示例

    CALL dbms_outline.insert_optimizer_outline('outline_db', '', 1, '/*+ BNL(t1,t2) */',
          "select t1.id, t2.id from t1,t2");
    mysql> explain select t1.id, t2.id from t1,t2;
    +----+-------------+-------+------------+-------+---------------+-------+---------+------+------+----------+----------------------------------------------------+
    | id | select_type | table | partitions | type  | possible_keys | key   | key_len | ref  | rows | filtered | Extra                                              |
    +----+-------------+-------+------------+-------+---------------+-------+---------+------+------+----------+----------------------------------------------------+
    |  1 | SIMPLE      | t1    | NULL       | index | NULL          | ind_1 | 5       | NULL |    1 |   100.00 | Using index                                        |
    |  1 | SIMPLE      | t2    | NULL       | index | NULL          | ind_1 | 5       | NULL |    1 |   100.00 | Using index; Using join buffer (Block Nested Loop) |
    +----+-------------+-------+------------+-------+---------------+-------+---------+------+------+----------+----------------------------------------------------+
    2 rows in set, 1 warning (0.01 sec)
    mysql> show warnings;
    +-------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Level | Code | Message                                                                                                                                                                            |
    +-------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Note  | 1003 | /* select#1 */ select /*+ BNL(`t1`@`select#1`) BNL(`t2`@`select#1`) */ `outline_db`.`t1`.`id` AS `id`,`outline_db`.`t2`.`id` AS `id` from `outline_db`.`t1` join `outline_db`.`t2` |
    +-------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)
    
  • 示例说明:

    • BNL 表示 Block Nested Loop,这是一种表连接算法。其核心逻辑是:

      • 将驱动表(如 t1)的数据按块(Block)加载到内存中

      • 在内存块中逐行与被驱动表(如 t2)的数据进行匹配

      • 适用于驱动表较小且被驱动表无高效索引的场景。

    • 作用对象 BNL(t1, t2)表示强制优化器在表 t1t2的关联操作中采用块嵌套循环连接算法。

子查询(subquery)相关的

  • 设置子查询的 Query block 标识

    CALL dbms_outline.insert_optimizer_outline('outline_db', '', 2, ' /*+ QB_NAME(subq1) */', 
          "SELECT * FROM t1 WHERE t1.col1 IN (SELECT col1 FROM t2)");
    
  • 使用 SEMIJOIN 相关 HINT

    CALL dbms_outline.insert_optimizer_outline('outline_db', '', 1, '/*+ SEMIJOIN(@subq1 MATERIALIZATION, DUPSWEEDOUT) */ ',
          "SELECT * FROM t1 WHERE t1.col1 IN (SELECT col1 FROM t2)");
    
  • 示例说明:

    • SEMIJOIN 表示该提示针对半连接操作,即通过子查询(如 INEXISTS)筛选主表数据时,仅匹配子查询中至少一条相关记录的场景

    • @subq1 标识需要优化的子查询名称或别名,此处为上一个 Outline 指定的子查询名称

    • MATERIALIZATION 物化策略:强制将子查询的结果临时存储在内存或磁盘中,避免重复计算。适用于子查询结果集较小但需要多次访问的场景

    • DUPSWEEDOUT 去重策略:在子查询结果中消除重复值,确保主查询仅匹配唯一值。常用于子查询可能返回重复数据时优化性能

  • 效果验证

    mysql> explain SELECT * FROM t1 WHERE t1.col1 IN (SELECT col1 FROM t2);
    +----+--------------+-------------+------------+--------+---------------------+---------------------+---------+--------------------+------+----------+-------------+
    | id | select_type  | table       | partitions | type   | possible_keys       | key                 | key_len | ref                | rows | filtered | Extra       |
    +----+--------------+-------------+------------+--------+---------------------+---------------------+---------+--------------------+------+----------+-------------+
    |  1 | SIMPLE       | t1          | NULL       | ALL    | ind_1               | NULL                | NULL    | NULL               |    1 |   100.00 | Using where |
    |  1 | SIMPLE       | <subquery2> | NULL       | eq_ref | <auto_distinct_key> | <auto_distinct_key> | 5       | outline_db.t1.col1 |    1 |   100.00 | NULL        |
    |  2 | MATERIALIZED | t2          | NULL       | index  | ind_1               | ind_1               | 5       | NULL               |    1 |   100.00 | Using index |
    +----+--------------+-------------+------------+--------+---------------------+---------------------+---------+--------------------+------+----------+-------------+
    3 rows in set, 1 warning (0.00 sec)
    mysql> show warnings;
    +-------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Level | Code | Message                                                                                                                                                                                                                                                                                        |
    +-------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Note  | 1003 | /* select#1 */ select /*+ SEMIJOIN(@`subq1` MATERIALIZATION, DUPSWEEDOUT) */ `outline_db`.`t1`.`id` AS `id`,`outline_db`.`t1`.`col1` AS `col1`,`outline_db`.`t1`.`col2` AS `col2` from `outline_db`.`t1` semi join (`outline_db`.`t2`) where (`<subquery2>`.`col1` = `outline_db`.`t1`.`col1`) |
    +-------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)
    

设置运行时变量

  • 通过以下hint可以单独对语句设置变量

    /*+ SET_VAR(<var_name>=<var_value>) */
    

Outline 示例:

  • 设置最大查询时间 MAX_EXECUTION_TIME

    CALL dbms_outline.insert_optimizer_outline("outline_db", '', 1, '/*+ MAX_EXECUTION_TIME(1000) */',
          "select * from t1 where id = 1");
    
  • 设置外键约束 foreign_key_checks

    CALL dbms_outline.insert_optimizer_outline("outline_db", '', 1, '/*+ SET_VAR(foreign_key_checks=OFF) */',
        "select * from t1 where id = 1");
    
  • 效果验证

    mysql> explain select * from t1 where id = 1;
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+
    | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                          |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+
    |  1 | SIMPLE      | NULL  | NULL       | NULL | NULL          | NULL | NULL    | NULL | NULL |     NULL | no matching row in const table |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+
    1 row in set, 1 warning (0.01 sec)
    mysql> show warnings;
    +-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Level | Code | Message                                                                                                                                                                                 |
    +-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Note  | 1003 | /* select#1 */ select /*+ MAX_EXECUTION_TIME(1000) SET_VAR(foreign_key_checks='OFF') */ NULL AS `id`,NULL AS `col1`,NULL AS `col2` from `outline_db`.`t1` where multiple equal(1, NULL) |
    +-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)
    

FAQ

云数据库 MySQL 版如何处理互相矛盾的 Outline?

如果用户插入了两条矛盾的 Outline,实际起作用的 hint 由 MySQL 的 hint resolve 逻辑决定。详情请参考MySQL文档

  • 示例

    mysql> CALL dbms_outline.display_outline();
    
    +------+------------+------------------------------------------------------------------+-----------+-------+------+-------------------------------------------------------+------+----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | ID   | SCHEMA     | DIGEST                                                           | TYPE      | SCOPE | POS  | HINT                                                  | HIT  | OVERFLOW | DIGEST_TEXT                                                                                                                                                                                                                            |
    +------+------------+------------------------------------------------------------------+-----------+-------+------+-------------------------------------------------------+------+----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    |   14 |            | d9bc7ca4b466e3eff5c35133b62328b340e7996a20c0a3278f44e81908516796 | OPTIMIZER |       |    2 |  /*+ QB_NAME(subq2) */                                |    6 |        0 | SELECT * FROM `db1` . `t1` WHERE `t1` . `col1` IN ( SELECT `col1` FROM `db1` . `t2` )                                                                                                                                                  |
    |   15 |            | d9bc7ca4b466e3eff5c35133b62328b340e7996a20c0a3278f44e81908516796 | OPTIMIZER |       |    2 |  /*+ NO_INDEX(t1) */                                  |    2 |        0 | SELECT * FROM `db1` . `t1` WHERE `t1` . `col1` IN ( SELECT `col1` FROM `db1` . `t2` )                                                                                                                                                  |
    |   16 |            | d9bc7ca4b466e3eff5c35133b62328b340e7996a20c0a3278f44e81908516796 | OPTIMIZER |       |    2 |  /*+ INDEX(t1) */                                     |    2 |        0 | SELECT * FROM `db1` . `t1` WHERE `t1` . `col1` IN ( SELECT `col1` FROM `db1` . `t2` )                                                                                                                                                  |
    |   17 |            | d9bc7ca4b466e3eff5c35133b62328b340e7996a20c0a3278f44e81908516796 | OPTIMIZER |       |    2 |  /*+ INDEX(t2) */                                     |    0 |        0 | SELECT * FROM `db1` . `t1` WHERE `t1` . `col1` IN ( SELECT `col1` FROM `db1` . `t2` )                                                                                                                                                  |
    |   18 |            | d9bc7ca4b466e3eff5c35133b62328b340e7996a20c0a3278f44e81908516796 | OPTIMIZER |       |    2 |  /*+ NO_INDEX(t2) */                                  |    0 |        0 | SELECT * FROM `db1` . `t1` WHERE `t1` . `col1` IN ( SELECT `col1` FROM `db1` . `t2` )                                                                                                                                                  |
    +------+------------+------------------------------------------------------------------+-----------+-------+------+-------------------------------------------------------+------+----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    
    mysql> CALL dbms_outline.check_outline('', 'SELECT * FROM db1.t1 WHERE t1.col1 IN (SELECT col1 FROM db1.t2)');
    +--------+------------------------------------------------------------------+------------+------------+-------+----------------------------------------------------+
    | SCHEMA | DIGEST                                                           | BLOCK_TYPE | BLOCK_NAME | BLOCK | HINT                                               |
    +--------+------------------------------------------------------------------+------------+------------+-------+----------------------------------------------------+
    |        | d9bc7ca4b466e3eff5c35133b62328b340e7996a20c0a3278f44e81908516796 | QUERY      |            |     1 | /*+ NO_INDEX(`t1`@`subq2`) INDEX(`t2`@`subq2`) */  |
    |        | d9bc7ca4b466e3eff5c35133b62328b340e7996a20c0a3278f44e81908516796 | QUERY      |            |     2 | /*+ QB_NAME(`subq2`) */                            |
    +--------+------------------------------------------------------------------+------------+------------+-------+----------------------------------------------------+
    2 rows in set, 2 warnings (0.00 sec)
    
    mysql> show warnings;
    +---------+------+-----------------------------------------------------------+
    | Level   | Code | Message                                                   |
    +---------+------+-----------------------------------------------------------+
    | Warning | 3126 | Hint INDEX(`t1` ) is ignored as conflicting/duplicated    |
    | Warning | 3126 | Hint NO_INDEX(`t2` ) is ignored as conflicting/duplicated |
    +---------+------+-----------------------------------------------------------+
    2 rows in set (0.00 sec)
    
  • 示例说明

    • Query block 2 中只有 t2,但 Outline 指定了对于 t1 的 index,而且对 t2 的 index 同时指定了 NO_INDEX 和 INDEX。这时候虽然所有 hint 都能匹配,但是最后生效的是第一个插入的 Outline:NO_INDEX(t1)INDEX(t2)

    • 如果出现矛盾的 Outline,会返回警告,使用SHOW WARNINGS 查看警告内容。


Outline 在什么节点添加、生效?

  • Outline 相关管理 SQL 接口只能在主节点执行,调用下列 SQL 接口之后,Outline 的修改自动会同步至所有只读节点和备节点并且生效:

    • insert_optimizer_outline

    • insert_index_outline

    • delete_outline

  • Outline 验证以及显示接口可在任意节点执行:

    • display_outline

    • check_outline

开启 Statement outline 后,对数据库性能是否有影响?

开启 Statement outline 后,SQL 执行时会计算一次 SQL 指纹。
对性能几乎无影响,在受 SQL 指纹计算影响最大的 CPU-bound 性能测试中,Outline 对性能的影响 < 3%。

备份恢复会恢复系统中 Outline 吗?

  • 如果您选择了「恢复到新实例」,会从新实例全量恢复实例数据到指定时间点,系统中保存的 Outline 也表将会回到指定时间点的状态。

  • 如果您选择了「恢复到原实例」,您将指定用户库表进行恢复,此时 Outline 将保持原样。