前言
pg_hint_plan技术内幕–02 Scan method中介绍的Scan Method场景,当我们使用hint指定索引时有可能走顺序扫描。
原因就是plantree里将表其余index剔除, 只保留hint指定的index,并且将seqscan的startup_cost配置为disable_cost,然后计算最小代价,哪种scan方式最小就会被选择为最终执行路径,有可能seqscan的cost更小,所以才会出现这样的情况。
分析
那么完全没有办法了?想强制100%让优化器走hint指定的索引无法实现了?
如下示例,IndexScan(dba_users dba_users_username_idx),没走指定的索引,走了seq scan
虽然seqscan的startup_cost被设置为disable_cost(10000000000即set enable_seqscan = off)
但是代价还是要比走指定的index要更小,因此优化器选择seqscan。
那么看起来是disable_cost不够大,如果再增大到一定范围,指定的index scan的cost就会小于seqscan
但是disable_cost在内核中,只是一个cost常量10000000000,并不是一个guc parameter。
方案
那么方案就来了,可以将disable_cost改变为一个guc parameter
涉及的代码很简单:
默认值和最小值为1.0e10, 最大值为1.0e20,参数类型为PGC_USERSET,set就可以设置
验证
在指定索引的同时 Set(disable_cost 1e+15),可以看到符合预期,走了指定的索引。
同样session里set disable_cost to 1e+15;也是可以的。
验证参数范围区间:
小结
笔者很多次遇到由于disable_cost不够大,导致无法使用hint强制走指定的索引的场景,本篇尝试将其设置为一个guc参数可以动态调整,对于这样的场景就能够精准打击。当然指定的索引对于查询条件来说要是合理的。