@@ -1990,9 +1990,14 @@ explain (analyze, costs off, summary off, timing off) select * from list_part wh
19901990rollback;
19911991drop table list_part;
19921992-- Parallel append
1993- -- Suppress the number of loops each parallel node runs for. This is because
1994- -- more than one worker may run the same parallel node if timing conditions
1995- -- are just right, which destabilizes the test.
1993+ -- Parallel queries won't necessarily get as many workers as the planner
1994+ -- asked for. This affects not only the "Workers Launched:" field of EXPLAIN
1995+ -- results, but also row counts and loop counts for parallel scans, Gathers,
1996+ -- and everything in between. This function filters out the values we can't
1997+ -- rely on to be stable.
1998+ -- This removes enough info that you might wonder why bother with EXPLAIN
1999+ -- ANALYZE at all. The answer is that we need to see '(never executed)'
2000+ -- notations because that's the only way to verify runtime pruning.
19962001create function explain_parallel_append(text) returns setof text
19972002language plpgsql as
19982003$$
@@ -2003,9 +2008,8 @@ begin
20032008 execute format('explain (analyze, costs off, summary off, timing off) %s',
20042009 $1)
20052010 loop
2006- if ln like '%Parallel%' then
2007- ln := regexp_replace(ln, 'loops=\d*', 'loops=N');
2008- end if;
2011+ ln := regexp_replace(ln, 'Workers Launched: \d+', 'Workers Launched: N');
2012+ ln := regexp_replace(ln, 'actual rows=\d+ loops=\d+', 'actual rows=N loops=N');
20092013 return next ln;
20102014 end loop;
20112015end;
@@ -2052,18 +2056,18 @@ execute ab_q4 (1, 8);
20522056select explain_parallel_append('execute ab_q4 (2, 2)');
20532057 explain_parallel_append
20542058-------------------------------------------------------------------------------
2055- Finalize Aggregate (actual rows=1 loops=1 )
2056- -> Gather (actual rows=3 loops=1 )
2059+ Finalize Aggregate (actual rows=N loops=N )
2060+ -> Gather (actual rows=N loops=N )
20572061 Workers Planned: 2
2058- Workers Launched: 2
2059- -> Partial Aggregate (actual rows=1 loops=3 )
2060- -> Parallel Append (actual rows=0 loops=N)
2062+ Workers Launched: N
2063+ -> Partial Aggregate (actual rows=N loops=N )
2064+ -> Parallel Append (actual rows=N loops=N)
20612065 Subplans Removed: 6
2062- -> Parallel Seq Scan on ab_a2_b1 (actual rows=0 loops=N)
2066+ -> Parallel Seq Scan on ab_a2_b1 (actual rows=N loops=N)
20632067 Filter: ((a >= $1) AND (a <= $2) AND (b < 4))
2064- -> Parallel Seq Scan on ab_a2_b2 (actual rows=0 loops=N)
2068+ -> Parallel Seq Scan on ab_a2_b2 (actual rows=N loops=N)
20652069 Filter: ((a >= $1) AND (a <= $2) AND (b < 4))
2066- -> Parallel Seq Scan on ab_a2_b3 (actual rows=0 loops=N)
2070+ -> Parallel Seq Scan on ab_a2_b3 (actual rows=N loops=N)
20672071 Filter: ((a >= $1) AND (a <= $2) AND (b < 4))
20682072(13 rows)
20692073
@@ -2105,42 +2109,42 @@ execute ab_q5 (1, 2, 3);
21052109select explain_parallel_append('execute ab_q5 (1, 1, 1)');
21062110 explain_parallel_append
21072111-------------------------------------------------------------------------------
2108- Finalize Aggregate (actual rows=1 loops=1 )
2109- -> Gather (actual rows=3 loops=1 )
2112+ Finalize Aggregate (actual rows=N loops=N )
2113+ -> Gather (actual rows=N loops=N )
21102114 Workers Planned: 2
2111- Workers Launched: 2
2112- -> Partial Aggregate (actual rows=1 loops=3 )
2113- -> Parallel Append (actual rows=0 loops=N)
2115+ Workers Launched: N
2116+ -> Partial Aggregate (actual rows=N loops=N )
2117+ -> Parallel Append (actual rows=N loops=N)
21142118 Subplans Removed: 6
2115- -> Parallel Seq Scan on ab_a1_b1 (actual rows=0 loops=N)
2119+ -> Parallel Seq Scan on ab_a1_b1 (actual rows=N loops=N)
21162120 Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
2117- -> Parallel Seq Scan on ab_a1_b2 (actual rows=0 loops=N)
2121+ -> Parallel Seq Scan on ab_a1_b2 (actual rows=N loops=N)
21182122 Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
2119- -> Parallel Seq Scan on ab_a1_b3 (actual rows=0 loops=N)
2123+ -> Parallel Seq Scan on ab_a1_b3 (actual rows=N loops=N)
21202124 Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
21212125(13 rows)
21222126
21232127select explain_parallel_append('execute ab_q5 (2, 3, 3)');
21242128 explain_parallel_append
21252129-------------------------------------------------------------------------------
2126- Finalize Aggregate (actual rows=1 loops=1 )
2127- -> Gather (actual rows=3 loops=1 )
2130+ Finalize Aggregate (actual rows=N loops=N )
2131+ -> Gather (actual rows=N loops=N )
21282132 Workers Planned: 2
2129- Workers Launched: 2
2130- -> Partial Aggregate (actual rows=1 loops=3 )
2131- -> Parallel Append (actual rows=0 loops=N)
2133+ Workers Launched: N
2134+ -> Partial Aggregate (actual rows=N loops=N )
2135+ -> Parallel Append (actual rows=N loops=N)
21322136 Subplans Removed: 3
2133- -> Parallel Seq Scan on ab_a2_b1 (actual rows=0 loops=N)
2137+ -> Parallel Seq Scan on ab_a2_b1 (actual rows=N loops=N)
21342138 Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
2135- -> Parallel Seq Scan on ab_a2_b2 (actual rows=0 loops=N)
2139+ -> Parallel Seq Scan on ab_a2_b2 (actual rows=N loops=N)
21362140 Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
2137- -> Parallel Seq Scan on ab_a2_b3 (actual rows=0 loops=N)
2141+ -> Parallel Seq Scan on ab_a2_b3 (actual rows=N loops=N)
21382142 Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
2139- -> Parallel Seq Scan on ab_a3_b1 (actual rows=0 loops=N)
2143+ -> Parallel Seq Scan on ab_a3_b1 (actual rows=N loops=N)
21402144 Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
2141- -> Parallel Seq Scan on ab_a3_b2 (actual rows=0 loops=N)
2145+ -> Parallel Seq Scan on ab_a3_b2 (actual rows=N loops=N)
21422146 Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
2143- -> Parallel Seq Scan on ab_a3_b3 (actual rows=0 loops=N)
2147+ -> Parallel Seq Scan on ab_a3_b3 (actual rows=N loops=N)
21442148 Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
21452149(19 rows)
21462150
@@ -2149,12 +2153,12 @@ select explain_parallel_append('execute ab_q5 (2, 3, 3)');
21492153select explain_parallel_append('execute ab_q5 (33, 44, 55)');
21502154 explain_parallel_append
21512155-------------------------------------------------------------------------------
2152- Finalize Aggregate (actual rows=1 loops=1 )
2153- -> Gather (actual rows=3 loops=1 )
2156+ Finalize Aggregate (actual rows=N loops=N )
2157+ -> Gather (actual rows=N loops=N )
21542158 Workers Planned: 2
2155- Workers Launched: 2
2156- -> Partial Aggregate (actual rows=1 loops=3 )
2157- -> Parallel Append (actual rows=0 loops=N)
2159+ Workers Launched: N
2160+ -> Partial Aggregate (actual rows=N loops=N )
2161+ -> Parallel Append (actual rows=N loops=N)
21582162 Subplans Removed: 8
21592163 -> Parallel Seq Scan on ab_a1_b1 (never executed)
21602164 Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
@@ -2164,21 +2168,21 @@ select explain_parallel_append('execute ab_q5 (33, 44, 55)');
21642168select explain_parallel_append('select count(*) from ab where (a = (select 1) or a = (select 3)) and b = 2');
21652169 explain_parallel_append
21662170-------------------------------------------------------------------------
2167- Aggregate (actual rows=1 loops=1 )
2171+ Aggregate (actual rows=N loops=N )
21682172 InitPlan 1 (returns $0)
2169- -> Result (actual rows=1 loops=1 )
2173+ -> Result (actual rows=N loops=N )
21702174 InitPlan 2 (returns $1)
2171- -> Result (actual rows=1 loops=1 )
2172- -> Gather (actual rows=0 loops=1 )
2175+ -> Result (actual rows=N loops=N )
2176+ -> Gather (actual rows=N loops=N )
21732177 Workers Planned: 2
21742178 Params Evaluated: $0, $1
2175- Workers Launched: 2
2176- -> Parallel Append (actual rows=0 loops=N)
2177- -> Parallel Seq Scan on ab_a1_b2 (actual rows=0 loops=N)
2179+ Workers Launched: N
2180+ -> Parallel Append (actual rows=N loops=N)
2181+ -> Parallel Seq Scan on ab_a1_b2 (actual rows=N loops=N)
21782182 Filter: ((b = 2) AND ((a = $0) OR (a = $1)))
21792183 -> Parallel Seq Scan on ab_a2_b2 (never executed)
21802184 Filter: ((b = 2) AND ((a = $0) OR (a = $1)))
2181- -> Parallel Seq Scan on ab_a3_b2 (actual rows=0 loops=N)
2185+ -> Parallel Seq Scan on ab_a3_b2 (actual rows=N loops=N)
21822186 Filter: ((b = 2) AND ((a = $0) OR (a = $1)))
21832187(16 rows)
21842188
@@ -2203,20 +2207,20 @@ set enable_mergejoin = 0;
22032207select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on ab.a = a.a where a.a in(0, 0, 1)');
22042208 explain_parallel_append
22052209---------------------------------------------------------------------------------------------------
2206- Finalize Aggregate (actual rows=1 loops=1 )
2207- -> Gather (actual rows=2 loops=1 )
2210+ Finalize Aggregate (actual rows=N loops=N )
2211+ -> Gather (actual rows=N loops=N )
22082212 Workers Planned: 1
2209- Workers Launched: 1
2210- -> Partial Aggregate (actual rows=1 loops=2 )
2211- -> Nested Loop (actual rows=0 loops=2 )
2212- -> Parallel Seq Scan on lprt_a a (actual rows=51 loops=N)
2213+ Workers Launched: N
2214+ -> Partial Aggregate (actual rows=N loops=N )
2215+ -> Nested Loop (actual rows=N loops=N )
2216+ -> Parallel Seq Scan on lprt_a a (actual rows=N loops=N)
22132217 Filter: (a = ANY ('{0,0,1}'::integer[]))
2214- -> Append (actual rows=0 loops=102 )
2215- -> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (actual rows=0 loops=2 )
2218+ -> Append (actual rows=N loops=N )
2219+ -> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (actual rows=N loops=N )
22162220 Index Cond: (a = a.a)
2217- -> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (actual rows=0 loops=2 )
2221+ -> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (actual rows=N loops=N )
22182222 Index Cond: (a = a.a)
2219- -> Index Scan using ab_a1_b3_a_idx on ab_a1_b3 (actual rows=0 loops=2 )
2223+ -> Index Scan using ab_a1_b3_a_idx on ab_a1_b3 (actual rows=N loops=N )
22202224 Index Cond: (a = a.a)
22212225 -> Index Scan using ab_a2_b1_a_idx on ab_a2_b1 (never executed)
22222226 Index Cond: (a = a.a)
@@ -2237,20 +2241,20 @@ select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on
22372241select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on ab.a = a.a + 0 where a.a in(0, 0, 1)');
22382242 explain_parallel_append
22392243---------------------------------------------------------------------------------------------------
2240- Finalize Aggregate (actual rows=1 loops=1 )
2241- -> Gather (actual rows=2 loops=1 )
2244+ Finalize Aggregate (actual rows=N loops=N )
2245+ -> Gather (actual rows=N loops=N )
22422246 Workers Planned: 1
2243- Workers Launched: 1
2244- -> Partial Aggregate (actual rows=1 loops=2 )
2245- -> Nested Loop (actual rows=0 loops=2 )
2246- -> Parallel Seq Scan on lprt_a a (actual rows=51 loops=N)
2247+ Workers Launched: N
2248+ -> Partial Aggregate (actual rows=N loops=N )
2249+ -> Nested Loop (actual rows=N loops=N )
2250+ -> Parallel Seq Scan on lprt_a a (actual rows=N loops=N)
22472251 Filter: (a = ANY ('{0,0,1}'::integer[]))
2248- -> Append (actual rows=0 loops=102 )
2249- -> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (actual rows=0 loops=2 )
2252+ -> Append (actual rows=N loops=N )
2253+ -> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (actual rows=N loops=N )
22502254 Index Cond: (a = (a.a + 0))
2251- -> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (actual rows=0 loops=2 )
2255+ -> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (actual rows=N loops=N )
22522256 Index Cond: (a = (a.a + 0))
2253- -> Index Scan using ab_a1_b3_a_idx on ab_a1_b3 (actual rows=0 loops=2 )
2257+ -> Index Scan using ab_a1_b3_a_idx on ab_a1_b3 (actual rows=N loops=N )
22542258 Index Cond: (a = (a.a + 0))
22552259 -> Index Scan using ab_a2_b1_a_idx on ab_a2_b1 (never executed)
22562260 Index Cond: (a = (a.a + 0))
@@ -2270,53 +2274,53 @@ insert into lprt_a values(3),(3);
22702274select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on ab.a = a.a where a.a in(1, 0, 3)');
22712275 explain_parallel_append
22722276---------------------------------------------------------------------------------------------------
2273- Finalize Aggregate (actual rows=1 loops=1 )
2274- -> Gather (actual rows=2 loops=1 )
2277+ Finalize Aggregate (actual rows=N loops=N )
2278+ -> Gather (actual rows=N loops=N )
22752279 Workers Planned: 1
2276- Workers Launched: 1
2277- -> Partial Aggregate (actual rows=1 loops=2 )
2278- -> Nested Loop (actual rows=0 loops=2 )
2279- -> Parallel Seq Scan on lprt_a a (actual rows=52 loops=N)
2280+ Workers Launched: N
2281+ -> Partial Aggregate (actual rows=N loops=N )
2282+ -> Nested Loop (actual rows=N loops=N )
2283+ -> Parallel Seq Scan on lprt_a a (actual rows=N loops=N)
22802284 Filter: (a = ANY ('{1,0,3}'::integer[]))
2281- -> Append (actual rows=0 loops=104 )
2282- -> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (actual rows=0 loops=2 )
2285+ -> Append (actual rows=N loops=N )
2286+ -> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (actual rows=N loops=N )
22832287 Index Cond: (a = a.a)
2284- -> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (actual rows=0 loops=2 )
2288+ -> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (actual rows=N loops=N )
22852289 Index Cond: (a = a.a)
2286- -> Index Scan using ab_a1_b3_a_idx on ab_a1_b3 (actual rows=0 loops=2 )
2290+ -> Index Scan using ab_a1_b3_a_idx on ab_a1_b3 (actual rows=N loops=N )
22872291 Index Cond: (a = a.a)
22882292 -> Index Scan using ab_a2_b1_a_idx on ab_a2_b1 (never executed)
22892293 Index Cond: (a = a.a)
22902294 -> Index Scan using ab_a2_b2_a_idx on ab_a2_b2 (never executed)
22912295 Index Cond: (a = a.a)
22922296 -> Index Scan using ab_a2_b3_a_idx on ab_a2_b3 (never executed)
22932297 Index Cond: (a = a.a)
2294- -> Index Scan using ab_a3_b1_a_idx on ab_a3_b1 (actual rows=0 loops=2 )
2298+ -> Index Scan using ab_a3_b1_a_idx on ab_a3_b1 (actual rows=N loops=N )
22952299 Index Cond: (a = a.a)
2296- -> Index Scan using ab_a3_b2_a_idx on ab_a3_b2 (actual rows=0 loops=2 )
2300+ -> Index Scan using ab_a3_b2_a_idx on ab_a3_b2 (actual rows=N loops=N )
22972301 Index Cond: (a = a.a)
2298- -> Index Scan using ab_a3_b3_a_idx on ab_a3_b3 (actual rows=0 loops=2 )
2302+ -> Index Scan using ab_a3_b3_a_idx on ab_a3_b3 (actual rows=N loops=N )
22992303 Index Cond: (a = a.a)
23002304(27 rows)
23012305
23022306select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on ab.a = a.a where a.a in(1, 0, 0)');
23032307 explain_parallel_append
23042308---------------------------------------------------------------------------------------------------
2305- Finalize Aggregate (actual rows=1 loops=1 )
2306- -> Gather (actual rows=2 loops=1 )
2309+ Finalize Aggregate (actual rows=N loops=N )
2310+ -> Gather (actual rows=N loops=N )
23072311 Workers Planned: 1
2308- Workers Launched: 1
2309- -> Partial Aggregate (actual rows=1 loops=2 )
2310- -> Nested Loop (actual rows=0 loops=2 )
2311- -> Parallel Seq Scan on lprt_a a (actual rows=51 loops=N)
2312+ Workers Launched: N
2313+ -> Partial Aggregate (actual rows=N loops=N )
2314+ -> Nested Loop (actual rows=N loops=N )
2315+ -> Parallel Seq Scan on lprt_a a (actual rows=N loops=N)
23122316 Filter: (a = ANY ('{1,0,0}'::integer[]))
23132317 Rows Removed by Filter: 1
2314- -> Append (actual rows=0 loops=102 )
2315- -> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (actual rows=0 loops=2 )
2318+ -> Append (actual rows=N loops=N )
2319+ -> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (actual rows=N loops=N )
23162320 Index Cond: (a = a.a)
2317- -> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (actual rows=0 loops=2 )
2321+ -> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (actual rows=N loops=N )
23182322 Index Cond: (a = a.a)
2319- -> Index Scan using ab_a1_b3_a_idx on ab_a1_b3 (actual rows=0 loops=2 )
2323+ -> Index Scan using ab_a1_b3_a_idx on ab_a1_b3 (actual rows=N loops=N )
23202324 Index Cond: (a = a.a)
23212325 -> Index Scan using ab_a2_b1_a_idx on ab_a2_b1 (never executed)
23222326 Index Cond: (a = a.a)
@@ -2336,16 +2340,16 @@ delete from lprt_a where a = 1;
23362340select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on ab.a = a.a where a.a in(1, 0, 0)');
23372341 explain_parallel_append
23382342--------------------------------------------------------------------------------------------
2339- Finalize Aggregate (actual rows=1 loops=1 )
2340- -> Gather (actual rows=2 loops=1 )
2343+ Finalize Aggregate (actual rows=N loops=N )
2344+ -> Gather (actual rows=N loops=N )
23412345 Workers Planned: 1
2342- Workers Launched: 1
2343- -> Partial Aggregate (actual rows=1 loops=2 )
2344- -> Nested Loop (actual rows=0 loops=2 )
2345- -> Parallel Seq Scan on lprt_a a (actual rows=50 loops=N)
2346+ Workers Launched: N
2347+ -> Partial Aggregate (actual rows=N loops=N )
2348+ -> Nested Loop (actual rows=N loops=N )
2349+ -> Parallel Seq Scan on lprt_a a (actual rows=N loops=N)
23462350 Filter: (a = ANY ('{1,0,0}'::integer[]))
23472351 Rows Removed by Filter: 1
2348- -> Append (actual rows=0 loops=100 )
2352+ -> Append (actual rows=N loops=N )
23492353 -> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (never executed)
23502354 Index Cond: (a = a.a)
23512355 -> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (never executed)
0 commit comments