PostgreSQL EXPLAIN ANALYZE中实际时间T0、T1的精确含义问询
PostgreSQL EXPLAIN ANALYZE中actual time的精确含义解析
目前不少资料(包括官方文档、pgMustard相关文章)对PostgreSQL EXPLAIN ANALYZE输出里的实际时间含义解释模糊,这里梳理三个核心影响因素:
- 输出内容
(actual time=<T0>..<T1> rows=<R> loops=<L>)中的T0与T1 - 线程结构:1个"leader"线程+若干并行"workers"线程
- 循环次数(loops,即节点执行次数)
官方示例与现有疑问
官方文档给出的示例查询及执行计划如下:
EXPLAIN ANALYZE SELECT * FROM tenk1 t1, tenk2 t2 WHERE t1.unique1 < 10 AND t1.unique2 = t2.unique2;
QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------- Nested Loop (cost=4.65..118.62 rows=10 width=488) (actual time=0.128..0.377 rows=10 loops=1) -> Bitmap Heap Scan on tenk1 t1 (cost=4.36..39.47 rows=10 width=244) (actual time=0.057..0.121 rows=10 loops=1) Recheck Cond: (unique1 < 10) -> Bitmap Index Scan on tenk1_unique1 (cost=0.00..4.36 rows=10 width=0) (actual time=0.024..0.024 rows=10 loops=1) Index Cond: (unique1 < 10) -> Index Scan using tenk2_unique2 on tenk2 t2 (cost=0.29..7.91 rows=1 width=244) (actual time=0.021..0.022 rows=1 loops=10) Index Cond: (unique2 = t1.unique2) Planning time: 0.181 ms Execution time: 0.501 ms
官方仅说明:当节点多次执行(loops>1)时,actual time和rows为单次执行的平均值,需乘以loops得到总耗时,但未明确T0的具体含义,由此引发以下疑问:
- 单线程且
loops=1时,若T0是节点启动时间、T1是完成时间,为何根节点T1(0.377ms)小于总执行时间(0.501ms)? - 多循环场景下(如示例中tenk2的Index Scan,
actual time=0.021..0.022 rows=1 loops=10),T0的含义到底是什么? - 多线程并行场景下,T0、T1与循环次数、线程数的关系如何?
T0与T1的精确含义及场景影响
基础定义
从PostgreSQL源码及内部逻辑可明确T0和T1的本质:
- T0:对于单次执行(
loops=1)的节点,T0是该节点开始执行时的墙钟时间(相对于整个查询启动的时间点);对于多次执行(loops>1)的节点,T0是单次循环中,节点从启动到输出第一行数据的平均时间,反映单次循环的启动/初始化开销。 - T1:对于单次执行的节点,T1是该节点执行完成时的墙钟时间;对于多次执行的节点,T1是单次循环的总平均耗时(从循环启动到该循环结束的时间)。
单线程场景影响
- loops=1:
- 节点总耗时为
T1 - T0,代表该节点从启动到完成的实际墙钟时间。 - 根节点T1小于总执行时间的原因:总执行时间包含了Planning time(计划生成时间)、执行计划阶段时间(根节点T1-T0),以及查询完成后的收尾工作(如资源释放、结果返回客户端的时间),根节点的T1仅标记执行计划执行阶段的结束,而非整个查询的结束。
- 节点总耗时为
- loops>1:
- 节点总耗时为
T1 * loops,这是所有循环的总墙钟时间(单线程下循环串行执行)。 - 以示例中tenk2的Index Scan为例:
loops=10表示该节点被触发10次(外层Nested Loop返回10行,每行触发一次内层扫描),T0=0.021ms是每次扫描从启动到找到第一行数据的平均时间,T1=0.022ms是每次扫描的总平均耗时,总耗时为0.022*10=0.220ms。
- 节点总耗时为
多线程(并行查询)场景影响
- 并行节点的
actual time统计的是所有worker线程与leader线程的总CPU时间的平均值(按loops计算),而非墙钟时间。因为并行执行时多个线程同时工作,墙钟时间会远小于总CPU时间。 loops在并行场景下指该并行节点被触发执行的次数,每次触发会启动一组worker线程,T0和T1是每组并行执行的平均时间:- T0是每组并行执行从启动到第一个worker输出第一行数据的平均时间;
- T1是每组并行执行从启动到所有worker完成任务的平均总CPU时间。
内容的提问来源于stack exchange,提问作者Learner
相关产品推荐
相关产品推荐

