基于湖库一体架构,统一管理结构化、半结构化与非结构化等多模态数据,一个系统承载事务处理、实时分析与 AI 工作负载。
Outline / Hint 常见问题
更新时间:2024-08-02 02:02
绑定 outline 失败原因排查
确认是否匹配 outline
确认 gv$ob_plan_cache_plan_stat (在 OceanBase 数据库 V4.x 之前版本为 gv$plan_cache_plan_stat) 视图中物理计划相关字段。
OUTLINE_DATA: 完全描述了当前计划的计划形态,和 explain outline/explain extended 中 outline data含义相同。
HINTS_INFO: 生成该计划时使用的 hint,和 explain extended 中 used hint 含义相同。
OUTLINE_ID: 生成计划所使用的用户创建 outline id,-1 时表示没有使用用户创建 outline
如果 OUTLINE_ID 为 -1 则创建的 outline 没有匹配到对应 sql 上,检查创建 outline 用户/sql id 等信息。
如何用 explain extended 验证 outline/hint 有效
将 outline data 添加到查询后(对于 OceanBase 数据库 V4.0 之前版本,还需要移除原始查询中的hint),使用 explain extended 查看计划是否符合预期及 used hint 是否包含所有 outline 中 hint。
1. 待验证查询。
create table t1(c1 int, c2 int);
create index idx1 on t1(c1);
create index idx2 on t1(c2);
select /*+index(t1 idx1)*/ * from t1 where c1 > 2 and c2 < 4;
create outline otl on 'xxxx' using hint
/*+
BEGIN_OUTLINE_DATA
INDEX(@"SEL$1" "oceanbase"."t1"@"SEL$1" "idx2")
OPTIMIZER_FEATURES_ENABLE('4.0.0.0')
END_OUTLINE_DATA
*/
2. explain 验证使用的 sql。
explain extended
select /*+
BEGIN_OUTLINE_DATA
INDEX(@"SEL$1" "oceanbase"."t1"@"SEL$1" "idx2")
OPTIMIZER_FEATURES_ENABLE('4.0.0.0')
END_OUTLINE_DATA
*/ * from t1 where c1 > 2 and c2 < 4;
对于 explain extended 结果,除了查看计划,对比这两部分
Used Hint:
-------------------------------------
/*+
.....
查看原始 outline data 中hint是否完全出现在这里
*/
Outline Data:
-------------------------------------
/*+
对比和待验证原始 outline data 是否一致
*/
注意
对于 Q1:select * from t1; 和 Q2: explain select * from t1; 是完全不同的查询,使用 sql id 绑定在 Q1 上的 outline 不会直接作用在 Q2 上,因此不能直接通过 explain Q1 来验证 outline 是否有效。
手动添加 hint 失效常见问题
MySQL 客户端连接, 连接串未添加 -c 导致 hint 失效
可以使用简单查询对这种情况进行识别验证,如查看一下查询计划是否开启并行。
create table t1(c1 int, c2 int);
explain select /*+parallel(2)*/ * from t1;
hint 表对象指定无效
当表对象有别名时,必须使用别名指定。
使用别名指定,有效。
select /*+index(a idx)*/ * from t1 a;使用非别名指定,无效。
select /*+index(t1 idx)*/ * from t1 a;必须指定别名的原因(不使用别名会导致含义不明),如下面查询语句。
select /*+index(t1 idx)*/ * from t1 a, t1 b ...;
use_hash / use_merge / use_nl 等 hint 失效
hint 语义及语法参见:Hint 概述。
要使 use_hash 必然有效,一定要指定连接顺序。下面这种写法仅指定了以 t2 为右表时使用 hash join,最终可能生成以 t2 为左表的 merge join/nest loop join 计划。
select /*+use_hash(t2)*/ * from t1, t2 where t1.c1 = t2.c1;
需要按照下面查询,先指定连接顺序。
select /*+leading(t1) use_hash(t2)*/ * from t1, t2 where t1.c1 = t2.c1;
qb_name 使用不当导致 hint 失效
qb_name 用于在查询中指定 hint 的生效 query block。如下方查询,表层查询和内层查询 qb_name 分别为 sel$1 与 sel$2,index(@sel$2 t1 idx) 写在表层 query block,但通过 sel$2 实际作用生效在内层 query block。
select /*+no_rewrite index(@sel$2 t1 idx) */ *
from (select * from t1 where c1 = 3);
因此,在创建视图时,不能直接在视图查询中通过 qb_name 指定 hint。
create view v1 as select /*+index(@sel$1 t1 idx)*/ * from t1 where c1 = 3;
hint 在原始视图中生效
select /*+index(@sel$1 t1 idx)*/ * from t1 where c1 = 3;
v1 中的 hint 已失效,因为此时 sel$1 为表层 query block 的 qb_name,表层 query block 中不存在 t1,因此 hint index(@sel$1 t1 idx) 失效。
select /*+no_rewrite*/ * from v1;
推荐使用方法:视图中添加 hint 时,直接使用不添加 qb_name 的 hint。
如果需要绑定计划,直接使用业务实际查询的 sql_id 通过原始查询的 outline data 创建 outline。
create view v1 as select /*+index(t1 idx)*/ * from t1 where c1 = 3;
在 OceanBase 数据库 V4.x 之前版本中 outline 常见失效原因
查询触发了基于代价改写
在 OceanBase V4.x 之前版本 outline data 中没有记录优化器进行的查询改写(部分改写 hint 说明),当发生基于代价改写会导致 outline data 固定计划失败,频繁出现的几种代价改写。
OR 展开。
USE_CONCAT / NO_EXPANDgroup by placement。
PLACE_GROUP_BY / NO_PLACE_GROUP_BYsemi to inner。
将 semi join 改写为 inner join 强制触发与禁止触发 hint:UNNEST / NO_UNNEST,需要添加在子查询的上层查询中,如下示例。
select /*+unnest*/ * from t1 where exists (select * from t2 where t2.c1 = t1.c1);或
select /*+unnest*/ * from t1 where t1.c1 in (select t2.c1 from t2);上述二种写法的查询语句可改写为如下形式。
select * from t1, (select distinct t2.c1 v_c1 from t2) v where v_c1 = t1.c1;注意
OceanBase 数据库 V4.x 开始使用
SEMI_TO_INNER / NO_SEMI_TO_INNERhint 控制这一改写,并添加在子查询中。
适用版本
OceanBase 数据库所有版本。