Part 1 – 对于 Hint
Hint 是嵌入 SQL 语句的对优化器进行提醒的信息,是 DBA 进行 SQL 优化的罕用伎俩。SQL 语句通过优化器 (规定优化(RBO)、代价优化(CBO)),通常会抉择正确的查问门路,然而智者千虑,必有一失,有时优化器也会抉择一个很差的打算,使得该条 SQL 查问变得很慢,此时须要 DBA 人为干涉(通过给 SQL 语句减少一个正文),通知优化器要抉择指定的拜访门路(full scan、index scan) 或 join 类型(merge、hash、lookup),使得该条 SQL 语句能够高效的运行。
Part 2 – Hint 的应用
通过 /+ … / 的正文模式放在 SELECT 关键字之后,多个 hint 之间用逗号隔开。
例如 select /+use_index(t, index1)/ * from t where a = 10 and b = 20;
如下图所示,通过 RBO 会失去如下 normalized plan,而 /+ use_index(t, index1)/ 将作用于 scan 抉择的过程,这将通知优化器在抉择表 t 的拜访门路 (① ② ③) 时,抉择②索引 index1。
Part 3 – Hint 在云溪数据库中的
解析和利用流程
整体流程如下图 3.1 所示:
图 3.1 hint 解析应用流程
第一步:输出带有 hint SQL 语句,如下所示
第二步:parser 编译解析;
第三步:将 AST 中的 hint 信息保留在 HintSet 中;
第四步:Builder 从 AST 中获取 hint 信息,将对应 hint 解析到 TableHint 和 IndexHint 构造体中;
第五步:normalized plan 阶段(RBO),通过调用 buildScan 为表构建 ScanFlags,调用 buildJoin 为表构建 JoinFlags;
第六步:在 CBO 阶段进行摸索时,依据组成员的 Flags 信息,通过开销大小,来阻止某些等价表达式的生成,并生成 hint 须要的表达式,从而减小搜寻空间;
第七步:生成 hint 作用之下的最优查问打算。
Part 4 – Hint 在云溪数据库中
不同阶段的表现形式
SQL 语句中:显示指定要在表 c 上强制应用 idx2,与 c 和 o 相干的 join 操作不容许应用 NLJ 算子;
通过 parser 后,hint 信息保留在 HintSet 中;
在 Builder 中,hint 信息以对象 index 和 table 为单位进行保留;
在规范化打算树和 Memo 构造体中,hint 信息存在对应的 Expr 构造体中。
具体流程如下图 4.1 所示:
图 4.1 hint 在不同阶段的表现形式图
Part 5 – Hint 对优化器的影响
图 5.1 构造解释:
图 5.1 hint 作用图
bestHT 存储着每个 Group 的代价最低的表达式。
exprHT 存储所有摸索进去的表达式。
Group 为逻辑等价的关系表达式的汇合。
在云溪数据库中 hint 影响打算的伎俩次要有两个,一个是摸索阶段中,缩小表达式的生成(例如指定 megejoin,失常状况下会生成 merge、lookup、hash 三种连贯类型,然而指定了 mergejoin,就会间接不生成其余的的表达式),如下①;另一个是代价计算阶段中返回一个很大的代价 hugeCost(例如针对 t1,指定 index1,而后对于其余的拜访办法,则会间接返回很大的代价),如下③。
Hint 对优化器的影响如下:
① 排除了若干操作,缩小了 Memo 构造体中表达式的个数,如下图 X 号所示;
② 决定相干 Group 的最优打算抉择,如下图 Group 1;
③ Group 1 中,#1 作为规范化表达式必然存在于组中,然而,它的代价被设置为 hugeCost;
③ 因为应用 ForceIndex,在摸索阶段应用其它索引的表达式不会被优化器抉择;
⑤ 最终影响最优打算树的抉择。