本文介绍如何使用 Statement outline 功能。
- MySQL 8.0 版本,且内核版本为 3.0.6.1 及以上。
- MySQL 5.7 版本,且内核版本为 2.0.6.2 及以上。
实例运行过程中,一些 SQL 的执行计划可能会发生非预期的变化,造成稳定性风险。
例如:
- 在线业务使用 order by limit n 的用法,在 n 值比较小的时候频繁出现执行计划变动影响性能,
- 数据量变化时,统计数据也会发生改变。这些变化可能引起优化器的代价选择出现错误判断,选择了非最优的索引。
临时解决办法如实例通过调整 optimizer_switch 参数,或者通过修改业务 SQL 添加 hint 来绑定执行计划,对业务都不够友好。而 Statement outline 功能可将 SQL 的执行计划与 SQL 查询模板绑定,用户无需修改 SQL 即可将查询计划固化,避免出现上述风险。
MySQL 通过 hint 提供了语句维度的优化器控制,通过将 hint 添加至 SQL 语句,即可对 SQL 查询器的决策进行干预:
Statement outline 功能支持把两类 Hint 绑定至 SQL 模板中,从而达到查询计划固化的效果。支持的 Hint 类型与 MySQL 一致:
云数据库 veDB MySQL 版的内置了 Outline 相关的原生存储过程(Native Package)工具包,用户可通过调用 dbms_outline 相关接口进行 Outline 的操作。
insert_optimizer_outline
说明
- Digest 和 Query(原始 SQL语句)可以任选其一。如果填写 Query,dbms_outline 会计算指纹(Digest)和 SQL 模板(Digest_text)。
- Query 语句中需要使用引号时,需要在 query 语句中给需要添加引号的部分添加单引号,并使用双引号包围 query。
说明
- Digest 和 Query(原始 SQL 语句)可以任选其一。如果填写 Query,dbms_outline 会计算指纹(Digest)和 SQL 模板(Digest_text)。
- Query 语句中需要使用引号时,需要在 query 语句中给需要添加引号的部分添加单引号,并使用双引号包围 query。
- 描述:验证 SQL 语句 Statement outline 的生效情况,如果找到了匹配值,该 SQL 模板将会应用指定的 Hint。
- 通过 EXPLAIN 语句也可以查看 Outline 是否生效。
- MySQL 8.0 支持了 EXPLAIN ANALYZE 语法,允许用户实际执行查询并给出详细的执行信息。适用于需要对查询性能进行详细分析的场景。开启 Statement Outline 后,您可以在 Explain Analyze 中验证 outline 的性能。
- 描述:查看系统中保存 Statement outline 以及生效情况。
说明
- HIT 表示该 Statement outline 命中的次数,
- OVERFLOW 表示该 Statement outline 只匹配了 schema 和 digest 而没有找到 Query Block 或相应的表的次数。
- 描述:删除内存和表中的某一条 Statement outline。
- 如果删除的 Outline 不存在,会返回警告,使用 SHOW WARNINGS 查看警告内容。
指定使用 t1 表的 idx_1 索引。
- BNL 表示 Block Nested Loop,这是一种表连接算法。其核心逻辑是:
- 将驱动表(如 t1)的数据按块(Block)加载到内存中。
- 在内存块中逐行与被驱动表(如 t2)的数据进行匹配。
- 作用对象 BNL(t1, t2) 表示强制优化器在表 t1 和 t2 的关联操作中采用块嵌套循环连接算法。
- SEMIJOIN 表示该提示针对半连接操作,即通过子查询(如 IN 或 EXISTS)筛选主表数据时,仅匹配子查询中至少一条相关记录的场景。
- @subq1 标识需要优化的子查询名称或别名,此处为上一个 Outline 指定的子查询名称。
- MATERIALIZATION 物化策略:强制将子查询的结果临时存储在内存或磁盘中,避免重复计算。适用于子查询结果集较小但需要多次访问的场景。
- DUPSWEEDOUT 去重策略:在子查询结果中消除重复值,确保主查询仅匹配唯一值。常用于子查询可能返回重复数据时优化性能。
- 设置最大查询时间 MAX_EXECUTION_TIME。
- 设置外键约束 foreign_key_checks。
veDB MySQL 如何处理互相矛盾的 Outline?
如果用户插入了两条矛盾的 Outline,实际起作用的 hint 由 MySQL 的 hint resolve 逻辑决定。详情请参考 MySQL文档。 - Query block 2 中只有 t2,但 Outline 指定了对于 t1 的 index,而且对 t2 的 index 同时指定了 NO_INDEX 和 INDEX。这时候虽然所有 hint 都能匹配,但是最后生效的是第一个插入的 Outline:NO_INDEX(t1) 与 INDEX(t2)。
- 如果出现矛盾的 Outline,会返回警告,使用 SHOW WARNINGS 查看警告内容。
- Outline 相关管理 SQL 接口只能在主节点执行,调用下列 SQL 接口之后,Outline 的修改自动会同步至所有只读节点并且生效:
- insert_optimizer_outline
- Outline 验证以及显示接口可在任意节点执行:
开启 Statement outline 后,对数据库性能是否有影响?
开启 Statement outline 后,SQL 执行时会计算一次 SQL 指纹。
对性能几乎无影响,在受 SQL 指纹计算影响最大的 CPU-bound 性能测试中,Outline 对性能的影响 < 3%。
- 如果您选择了「恢复到新实例」,会从新实例全量恢复实例数据到指定时间点,系统中保存的 Outline 也表将会回到指定时间点的状态。
- 如果您选择了「恢复到原实例」,您将指定用户库表进行恢复,此时 Outline 将保持原样。
升级 MySQL 版本对 Outline 有何影响?
MySQL 5.7 与 MySQL 8.0 对 SQL 指纹的计算方式不同,因此两个版本的 Outline 互不兼容。
如果您已在 MySQL 5.7 上添加了若干 Outline,在将 MySQL 实例的大版本从 5.7 升级到 8.0 时,云数据库 veDB MySQL 版将自动为您迁移相关 Outline。迁移完成后,生效 Outline 的 SQL 指纹将发生改变。
不同 MySQL 大版本支持的 HINT 类型、优化器决策有较大区别区别,MySQL 5.7 上的 Outline 在 MySQL 8.0 版本中未必是最优,并且可能会失效。我们建议您在在升级后,确认并验证所有 Outline,以免您的 SQL 查询使用了非预期的执行计划。