@@ -1990,9 +1990,14 @@ explain (analyze, costs off, summary off, timing off) select * from list_part wh
1990
1990
rollback;
1991
1991
drop table list_part;
1992
1992
-- 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.
1996
2001
create function explain_parallel_append(text) returns setof text
1997
2002
language plpgsql as
1998
2003
$$
@@ -2003,9 +2008,8 @@ begin
2003
2008
execute format('explain (analyze, costs off, summary off, timing off) %s',
2004
2009
$1)
2005
2010
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');
2009
2013
return next ln;
2010
2014
end loop;
2011
2015
end;
@@ -2052,18 +2056,18 @@ execute ab_q4 (1, 8);
2052
2056
select explain_parallel_append('execute ab_q4 (2, 2)');
2053
2057
explain_parallel_append
2054
2058
-------------------------------------------------------------------------------
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 )
2057
2061
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)
2061
2065
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)
2063
2067
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)
2065
2069
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)
2067
2071
Filter: ((a >= $1) AND (a <= $2) AND (b < 4))
2068
2072
(13 rows)
2069
2073
@@ -2105,42 +2109,42 @@ execute ab_q5 (1, 2, 3);
2105
2109
select explain_parallel_append('execute ab_q5 (1, 1, 1)');
2106
2110
explain_parallel_append
2107
2111
-------------------------------------------------------------------------------
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 )
2110
2114
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)
2114
2118
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)
2116
2120
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)
2118
2122
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)
2120
2124
Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
2121
2125
(13 rows)
2122
2126
2123
2127
select explain_parallel_append('execute ab_q5 (2, 3, 3)');
2124
2128
explain_parallel_append
2125
2129
-------------------------------------------------------------------------------
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 )
2128
2132
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)
2132
2136
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)
2134
2138
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)
2136
2140
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)
2138
2142
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)
2140
2144
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)
2142
2146
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)
2144
2148
Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
2145
2149
(19 rows)
2146
2150
@@ -2149,12 +2153,12 @@ select explain_parallel_append('execute ab_q5 (2, 3, 3)');
2149
2153
select explain_parallel_append('execute ab_q5 (33, 44, 55)');
2150
2154
explain_parallel_append
2151
2155
-------------------------------------------------------------------------------
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 )
2154
2158
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)
2158
2162
Subplans Removed: 8
2159
2163
-> Parallel Seq Scan on ab_a1_b1 (never executed)
2160
2164
Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
@@ -2164,21 +2168,21 @@ select explain_parallel_append('execute ab_q5 (33, 44, 55)');
2164
2168
select explain_parallel_append('select count(*) from ab where (a = (select 1) or a = (select 3)) and b = 2');
2165
2169
explain_parallel_append
2166
2170
-------------------------------------------------------------------------
2167
- Aggregate (actual rows=1 loops=1 )
2171
+ Aggregate (actual rows=N loops=N )
2168
2172
InitPlan 1 (returns $0)
2169
- -> Result (actual rows=1 loops=1 )
2173
+ -> Result (actual rows=N loops=N )
2170
2174
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 )
2173
2177
Workers Planned: 2
2174
2178
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)
2178
2182
Filter: ((b = 2) AND ((a = $0) OR (a = $1)))
2179
2183
-> Parallel Seq Scan on ab_a2_b2 (never executed)
2180
2184
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)
2182
2186
Filter: ((b = 2) AND ((a = $0) OR (a = $1)))
2183
2187
(16 rows)
2184
2188
@@ -2203,20 +2207,20 @@ set enable_mergejoin = 0;
2203
2207
select 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)');
2204
2208
explain_parallel_append
2205
2209
---------------------------------------------------------------------------------------------------
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 )
2208
2212
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)
2213
2217
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 )
2216
2220
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 )
2218
2222
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 )
2220
2224
Index Cond: (a = a.a)
2221
2225
-> Index Scan using ab_a2_b1_a_idx on ab_a2_b1 (never executed)
2222
2226
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
2237
2241
select 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)');
2238
2242
explain_parallel_append
2239
2243
---------------------------------------------------------------------------------------------------
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 )
2242
2246
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)
2247
2251
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 )
2250
2254
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 )
2252
2256
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 )
2254
2258
Index Cond: (a = (a.a + 0))
2255
2259
-> Index Scan using ab_a2_b1_a_idx on ab_a2_b1 (never executed)
2256
2260
Index Cond: (a = (a.a + 0))
@@ -2270,53 +2274,53 @@ insert into lprt_a values(3),(3);
2270
2274
select 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)');
2271
2275
explain_parallel_append
2272
2276
---------------------------------------------------------------------------------------------------
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 )
2275
2279
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)
2280
2284
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 )
2283
2287
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 )
2285
2289
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 )
2287
2291
Index Cond: (a = a.a)
2288
2292
-> Index Scan using ab_a2_b1_a_idx on ab_a2_b1 (never executed)
2289
2293
Index Cond: (a = a.a)
2290
2294
-> Index Scan using ab_a2_b2_a_idx on ab_a2_b2 (never executed)
2291
2295
Index Cond: (a = a.a)
2292
2296
-> Index Scan using ab_a2_b3_a_idx on ab_a2_b3 (never executed)
2293
2297
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 )
2295
2299
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 )
2297
2301
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 )
2299
2303
Index Cond: (a = a.a)
2300
2304
(27 rows)
2301
2305
2302
2306
select 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)');
2303
2307
explain_parallel_append
2304
2308
---------------------------------------------------------------------------------------------------
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 )
2307
2311
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)
2312
2316
Filter: (a = ANY ('{1,0,0}'::integer[]))
2313
2317
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 )
2316
2320
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 )
2318
2322
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 )
2320
2324
Index Cond: (a = a.a)
2321
2325
-> Index Scan using ab_a2_b1_a_idx on ab_a2_b1 (never executed)
2322
2326
Index Cond: (a = a.a)
@@ -2336,16 +2340,16 @@ delete from lprt_a where a = 1;
2336
2340
select 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)');
2337
2341
explain_parallel_append
2338
2342
--------------------------------------------------------------------------------------------
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 )
2341
2345
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)
2346
2350
Filter: (a = ANY ('{1,0,0}'::integer[]))
2347
2351
Rows Removed by Filter: 1
2348
- -> Append (actual rows=0 loops=100 )
2352
+ -> Append (actual rows=N loops=N )
2349
2353
-> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (never executed)
2350
2354
Index Cond: (a = a.a)
2351
2355
-> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (never executed)
0 commit comments