实际上,我们可以通过inject的功能,针对某个语句进行参数调整。
使用方法如下:
sp_inject_hint(
'',--sql语句或者片段
'',--参数调整说明,语法:参数名称(参数值)
'',--这条调整规则的名字,通过这个名字,我们可以通过 sp_deinject_hint('名字'),进行规则取消
null,true,true
);
--构造数据:
drop table if exists tab1;
create table tab1(v1 varchar(30000),v2 varchar(30000),v3 varchar(30000));
create index idx_tab1_v1 on tab1(v1);
--分析语句:
select/*+stat(tab1 100M)*/ * from tab1 where v1 like ? or v2 like ? limit 10
--如果这两个参数业务实际传入的都是 %,这个or拆分了是不是实际上效果更加不好?
--我们在保持全局参数为0的情况下,希望使用 OPTIMIZER_OR_NBEXP 为 2的效果,如何为这个语句修改参数?
--为特定语句修改参数 OPTIMIZER_OR_NBEXP 为 2
sf_inject_hint(
'* from tab1 where v1 like ? or v2 like ? limit',--sql语句或者片段
'OPTIMIZER_OR_NBEXP(2)',--参数调整说明,语法:参数名称(参数值)
'name001',--这条调整规则的名字,通过这个名字,我们可以通过 sp_deinject_hint('名字'),进行规则取消
null,true,true
);
--查看计划:确实修改成功了,or根据 OPTIMIZER_OR_NBEXP 为 2 的规则,作为一个整体处理了
1 #NSET2: [14558, 10, 152]
2 #PRJT2: [14558, 10, 152]; exp_num(4), is_atom(FALSE)
3 #TOPN2: [14558, 10, 152]; top_num(10)
4 #SLCT2: [14558, 9750000, 152]; ((TAB1.V1 LIKE exp_param(no:0) AND TAB1.V1 >= var4 AND TAB1.V1 < var5) OR (TAB1.V2 LIKE exp_param(no:1) AND TAB1.V2 >= var6 AND TAB1.V2 < var7))
5 #CSCN2: [14558, 100000000, 152]; INDEX33556346(TAB1)
-- 进行规则取消
sf_deinject_hint('name001'); -- 进行规则取消
--在查看语句计划,如下:
1 #NSET2: [8820, 10, 152]
2 #PRJT2: [8820, 10, 152]; exp_num(4), is_atom(FALSE)
3 #TOPN2: [8820, 10, 152]; top_num(10)
4 #UNION FOR OR2: [8820, 375000, 152]; key_num(1)
5 #BLKUP2: [4386, 187500, 152]; IDX_TAB1_V1(TAB1)
6 #SLCT2: [4386, 187500, 152]; TAB1.V1 LIKE exp_param(no:0)
7 #SSEK2: [4386, 187500, 152]; scan_type(ASC), IDX_TAB1_V1(TAB1), scan_range[exp11,exp11)
8 #BLKUP2: [4386, 187500, 152]; IDX_TAB1_V2(TAB1)
9 #SLCT2: [4386, 187500, 152]; TAB1.V2 LIKE exp_param(no:1)
10 #SSEK2: [4386, 187500, 152]; scan_type(ASC), IDX_TAB1_V2(TAB1), scan_range[exp11,exp11)
说明:从上面的过程和计划里的代价评估也可以看出:在统计信息靠谱的情况,优化器确实是在自己的思维逻辑里干活的、它是相当靠谱的——始终忠于选择评估代价最小的计划。你能从上面的例子中,看出这句话吗?
后面还有几个帮助大家理解的例子:
说明:如果我们在数据库上执行 sf_inject_hint发现带6个参数时,报错找不到函数,不用奇怪;这个是新版本上才扩展的,以前的只能精准匹配,不能片段匹配(模糊匹配)。
文章
阅读量
获赞