OceanBase V4 执行计划缓存,SQL 加了 hint 为什么不生效?

  1. OB 的计划缓存匹配规则是什么?是不是 SQL 文本完全一致才会命中缓存?
  2. 已经缓存了旧计划之后,新增 hint 的同文本 SQL 会不会继续复用旧计划?
  3. 如果想让 hint 马上生效,除了重启租户,有什么清理单条 SQL 计划缓存的办法?

@论坛小助手

关于 OceanBase V4 执行计划缓存和 Hint 的问题

根据您的提问,我会逐一解答您的问题。

1. SQL 加了 Hint 为什么不生效?

  • Hint 不生效的原因:如果在 SQL 中添加了 Hint,但是执行计划并没有按照预期的那样改变,可能有以下几个原因:
    • Hint 使用规则:从文档片段 1 可知,如果指定表行为但在本 Query Block 中没有找到该表,或者发生冲突,那么 Hint 将会无效。请确保您使用的 Hint 是正确的,并且符合语法。
    • 优化器的行为:OceanBase 数据库优化器是动态规划的,已经考虑了所有可能的最优路径(见文档片段 2)。因此,有时候即使指定了 Hint,优化器也可能认为原有的计划更好,从而忽略 Hint。

2. 计划缓存匹配规则是什么?是不是 SQL 文本完全一致才会命中缓存?

  • 计划缓存匹配规则:并不是 SQL 文本完全一致才会命中缓存。实际上,当数据库接收到一条 SQL 请求后,首先会通过 fast parser 模块对 SQL 文本做一次快速参数化,将常量参数替换为通配符 ?(如 SELECT * FROM t1 WHERE c1 = 1 被替换为 SELECT * FROM t1 WHERE c1 = ?),然后使用这个参数化的 SQL 文本去匹配计划缓存中的记录(详见文档片段 5 和 9)。
  • 因此,只要参数化后的 SQL 文本相同,就可以命中缓存。

3. 已经缓存了旧计划之后,新增 Hint 的同文本 SQL 会不会继续复用旧计划?

  • 如果一个 SQL 在加入新的 Hint 后再次被执行,而之前的计划已经被缓存在计划缓存中,那么因为参数化后的 SQL 文本发生了变化(增加了 Hint),它将会被视为一个新的查询请求。在这种情况下,系统不会直接复用旧的执行计划,而是会重新生成一个新的执行计划并保存到计划缓存中。

4. 如果想让 hint 马上生效,除了重启租户,有什么清理单条 SQL 计划缓存的办法?

  • 清理单条 SQL 的计划缓存:如果您希望使特定 SQL 的 Hint 立即生效,可以手动清理相关的计划缓存条目。具体的方法是使用 OCP 或者 OBProxy 等管理工具来清除指定 SQL 的执行计划缓存。不过,目前 OceanBase 直接提供的命令行工具 obd 或 obshell 对于这种操作的支持有限,更推荐的做法是在 OCP 上进行相关操作。
  • 此外,在某些版本中,可以通过执行一些内部命令或脚本来清理特定 SQL 的计划缓存,但这通常需要较高的权限且不建议非专业人员操作。建议您联系 OceanBase 支持团队获取具体的操作指南。

基于上述信息,您可以尝试以下步骤解决问题:

  1. 检查 Hint 的正确性:确保 Hint 的语法正确且适用场景正确。
  2. 查看 SQL 参数化后的文本:确认是否因 Hint 导致参数化后的 SQL 文本发生变化。
  3. 清理相关 SQL 的计划缓存:使用 OCP 或其他管理工具来清理特定 SQL 的执行计划缓存。

希望这些信息能够帮助到您!如有更多疑问,请随时告知。

检索到的文档如下:

  1. 阅读和管理 OceanBase 数据库 SQL 执行计划
  2. 计划缓存概述
  3. Hint
  4. 常见的 SQL 调优方式