注册
inject的用法 | 和优化器做朋友

inject的用法 | 和优化器做朋友

hql 2021/11/28 3165 6 2
摘要 我们都知道,优化器参数不能(乱)改;但是,如果我们发现某个参数调整对SQL语句有巨大的正向收益,又会忍不住很想改,那怎么办呢?

实际上,我们可以通过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)

说明:从上面的过程和计划里的代价评估也可以看出:在统计信息靠谱的情况,优化器确实是在自己的思维逻辑里干活的、它是相当靠谱的——始终忠于选择评估代价最小的计划。你能从上面的例子中,看出这句话吗?

后面还有几个帮助大家理解的例子:

例子场景1

16381136081.jpg

例子场景2

16381136921.jpg

说明:如果我们在数据库上执行 sf_inject_hint发现带6个参数时,报错找不到函数,不用奇怪;这个是新版本上才扩展的,以前的只能精准匹配,不能片段匹配(模糊匹配)。

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服