Auto_explain原理探究
前言
顾名思义,就是自动执行explain,我们可以推测下它的原理:插件的hook函数去调用explain对应的逻辑,然后打印执行计划到数据库日志。
如下示例,开启相关参数,执行sql时执行计划自动记录到了日志中。
原理
启用auto_explain,需要将其配置到shared_preload_libraries参数,这样在主进程启动时就会加载插件对应的so文件,初始化自定参数和hook函数。
生成执行计划是在planner里进行的,auto_explain只是在Execute阶段将计划打印出来,显式explain也是同理,只是打印计划。
当开启插件后,在sql执行阶段,ExecutorEnd函数中判断如果已经注册了hook函数,则进入explain_ExecutorEnd
如果sql执行时间msec >= auto_explain.log_min_duration参数,则进入后续打印执行计划逻辑。
进入关键函数ExplainPrintPlan调用ExplainNode,调用InstrEndLoop(planstate->instrument)计算当前plan node运行的starttime totaltime等信息。如果auto_explain.log_analyze参数为on,则计算当前plan node对应的startup_ms,total_ms,rows,nloops然后调用appendStringInfo(es->str)来传参拼接“actual time”信息。
从计划树自上而下每个node进行上述打印处理,将所有node处理结果放到一个字符数组,最终调用ereport()将整个字符数组也就是完整的执计划打印到数据库日志中。
debug关键过程:
explain_ExecutorEnd函数中:判断msec >= auto_explain.log_min_duration,且auto_explain.log_analyze为on
ExplainNode函数中:根据planstate->instrument计算出当前node运行的startup_ms,total_ms,rows,nloops,并且调用appendStringInfo(es->str)来传参拼接“actual time”
所有node处理完后,通过ereport()打印到日志。
小结
简单总结下auto_explain的原理:sql执行时插件的hook函数去调用explain对应的逻辑,然后打印执行计划到数据库日志。
不过,值得注意的是使用该插件会带来一些性能开销,详情可参考《auto_explain 的开销有多大》。
评论