前言
上一篇我们简单介绍了pg_hint_plan的核心原理,本文我们将深入探索hint中scan method的原理。
目前支持的scan method如下:
以IndexScan(table[ index…])为例,当我们期望强制走某个索引时,通常使用这个hint来实现。
但往往会存在不符合预期的情况,虽然hint强制走指定索引,但是最终走了seqscan。
要搞明白这里的原理,我们就必须深入内核去分析。
原理
使用框图来梳理这里的逻辑:
在set_rel_pathlist时进入hook,pg_hint_plan处理rel的indexlist,
只保留hint中指定的index,从list中delete其他unused index,
并将indexscan之外其他的scan method配置为disable_cost。
最后计算最小代价,确定最终的path。
因此,会存这个现象,虽然hint中指定了使用某个index但最终没走索引扫描,而走了顺序扫描。
因为hint指定index只是将表的其他索引从plantree中剔除
只保留指定的这个索引,但走这个索引的代价预估不一定是最小的。
debug关键过程做下验证:
restrict_indexes():
unused_indexes 有2个成员,rel->indexlist初始3个成员,循环遍历rel->indexlist将unused_indexes
剔除,最终rel->indexlist保留了一个成员,即hintname指定的index
setup_scan_method_enforcement() :
hint-> enforce_mask=2即enable_indexscan=on,将其余scan Method配置为off,设置disable_cost
这样就对于index_scan只保留了hint指定的index,以及将其余扫描方式startup_cost设置为disable_cost
进而去计算最小代价,确定最终的path
小结
本文深入分析了scan method的原理,从原理看使用IndexScan(table[ index…])无法100%确定就走我们预期的索引,有可能走顺序扫描。给我们的感觉就像本来想打击小日子,结果把棒子给揍了。难道不能够精准打击指哪打哪吗?其实是有办法的,请看下回分解。