@@ -1972,9 +1972,14 @@ explain (analyze, costs off, summary off, timing off) select * from list_part wh
1972
1972
rollback;
1973
1973
drop table list_part;
1974
1974
-- Parallel append
1975
- -- Suppress the number of loops each parallel node runs for. This is because
1976
- -- more than one worker may run the same parallel node if timing conditions
1977
- -- are just right, which destabilizes the test.
1975
+ -- Parallel queries won't necessarily get as many workers as the planner
1976
+ -- asked for. This affects not only the "Workers Launched:" field of EXPLAIN
1977
+ -- results, but also row counts and loop counts for parallel scans, Gathers,
1978
+ -- and everything in between. This function filters out the values we can't
1979
+ -- rely on to be stable.
1980
+ -- This removes enough info that you might wonder why bother with EXPLAIN
1981
+ -- ANALYZE at all. The answer is that we need to see '(never executed)'
1982
+ -- notations because that's the only way to verify runtime pruning.
1978
1983
create function explain_parallel_append(text) returns setof text
1979
1984
language plpgsql as
1980
1985
$$
@@ -1985,9 +1990,8 @@ begin
1985
1990
execute format('explain (analyze, costs off, summary off, timing off) %s',
1986
1991
$1)
1987
1992
loop
1988
- if ln like '%Parallel%' then
1989
- ln := regexp_replace(ln, 'loops=\d*', 'loops=N');
1990
- end if;
1993
+ ln := regexp_replace(ln, 'Workers Launched: \d+', 'Workers Launched: N');
1994
+ ln := regexp_replace(ln, 'actual rows=\d+ loops=\d+', 'actual rows=N loops=N');
1991
1995
return next ln;
1992
1996
end loop;
1993
1997
end;
@@ -2034,18 +2038,18 @@ execute ab_q4 (1, 8);
2034
2038
select explain_parallel_append('execute ab_q4 (2, 2)');
2035
2039
explain_parallel_append
2036
2040
-------------------------------------------------------------------------------
2037
- Finalize Aggregate (actual rows=1 loops=1 )
2038
- -> Gather (actual rows=3 loops=1 )
2041
+ Finalize Aggregate (actual rows=N loops=N )
2042
+ -> Gather (actual rows=N loops=N )
2039
2043
Workers Planned: 2
2040
- Workers Launched: 2
2041
- -> Partial Aggregate (actual rows=1 loops=3 )
2042
- -> Parallel Append (actual rows=0 loops=N)
2044
+ Workers Launched: N
2045
+ -> Partial Aggregate (actual rows=N loops=N )
2046
+ -> Parallel Append (actual rows=N loops=N)
2043
2047
Subplans Removed: 6
2044
- -> Parallel Seq Scan on ab_a2_b1 (actual rows=0 loops=N)
2048
+ -> Parallel Seq Scan on ab_a2_b1 (actual rows=N loops=N)
2045
2049
Filter: ((a >= $1) AND (a <= $2) AND (b < 4))
2046
- -> Parallel Seq Scan on ab_a2_b2 (actual rows=0 loops=N)
2050
+ -> Parallel Seq Scan on ab_a2_b2 (actual rows=N loops=N)
2047
2051
Filter: ((a >= $1) AND (a <= $2) AND (b < 4))
2048
- -> Parallel Seq Scan on ab_a2_b3 (actual rows=0 loops=N)
2052
+ -> Parallel Seq Scan on ab_a2_b3 (actual rows=N loops=N)
2049
2053
Filter: ((a >= $1) AND (a <= $2) AND (b < 4))
2050
2054
(13 rows)
2051
2055
@@ -2087,42 +2091,42 @@ execute ab_q5 (1, 2, 3);
2087
2091
select explain_parallel_append('execute ab_q5 (1, 1, 1)');
2088
2092
explain_parallel_append
2089
2093
-------------------------------------------------------------------------------
2090
- Finalize Aggregate (actual rows=1 loops=1 )
2091
- -> Gather (actual rows=3 loops=1 )
2094
+ Finalize Aggregate (actual rows=N loops=N )
2095
+ -> Gather (actual rows=N loops=N )
2092
2096
Workers Planned: 2
2093
- Workers Launched: 2
2094
- -> Partial Aggregate (actual rows=1 loops=3 )
2095
- -> Parallel Append (actual rows=0 loops=N)
2097
+ Workers Launched: N
2098
+ -> Partial Aggregate (actual rows=N loops=N )
2099
+ -> Parallel Append (actual rows=N loops=N)
2096
2100
Subplans Removed: 6
2097
- -> Parallel Seq Scan on ab_a1_b1 (actual rows=0 loops=N)
2101
+ -> Parallel Seq Scan on ab_a1_b1 (actual rows=N loops=N)
2098
2102
Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
2099
- -> Parallel Seq Scan on ab_a1_b2 (actual rows=0 loops=N)
2103
+ -> Parallel Seq Scan on ab_a1_b2 (actual rows=N loops=N)
2100
2104
Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
2101
- -> Parallel Seq Scan on ab_a1_b3 (actual rows=0 loops=N)
2105
+ -> Parallel Seq Scan on ab_a1_b3 (actual rows=N loops=N)
2102
2106
Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
2103
2107
(13 rows)
2104
2108
2105
2109
select explain_parallel_append('execute ab_q5 (2, 3, 3)');
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: 3
2115
- -> Parallel Seq Scan on ab_a2_b1 (actual rows=0 loops=N)
2119
+ -> Parallel Seq Scan on ab_a2_b1 (actual rows=N loops=N)
2116
2120
Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
2117
- -> Parallel Seq Scan on ab_a2_b2 (actual rows=0 loops=N)
2121
+ -> Parallel Seq Scan on ab_a2_b2 (actual rows=N loops=N)
2118
2122
Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
2119
- -> Parallel Seq Scan on ab_a2_b3 (actual rows=0 loops=N)
2123
+ -> Parallel Seq Scan on ab_a2_b3 (actual rows=N loops=N)
2120
2124
Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
2121
- -> Parallel Seq Scan on ab_a3_b1 (actual rows=0 loops=N)
2125
+ -> Parallel Seq Scan on ab_a3_b1 (actual rows=N loops=N)
2122
2126
Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
2123
- -> Parallel Seq Scan on ab_a3_b2 (actual rows=0 loops=N)
2127
+ -> Parallel Seq Scan on ab_a3_b2 (actual rows=N loops=N)
2124
2128
Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
2125
- -> Parallel Seq Scan on ab_a3_b3 (actual rows=0 loops=N)
2129
+ -> Parallel Seq Scan on ab_a3_b3 (actual rows=N loops=N)
2126
2130
Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
2127
2131
(19 rows)
2128
2132
@@ -2131,12 +2135,12 @@ select explain_parallel_append('execute ab_q5 (2, 3, 3)');
2131
2135
select explain_parallel_append('execute ab_q5 (33, 44, 55)');
2132
2136
explain_parallel_append
2133
2137
-------------------------------------------------------------------------------
2134
- Finalize Aggregate (actual rows=1 loops=1 )
2135
- -> Gather (actual rows=3 loops=1 )
2138
+ Finalize Aggregate (actual rows=N loops=N )
2139
+ -> Gather (actual rows=N loops=N )
2136
2140
Workers Planned: 2
2137
- Workers Launched: 2
2138
- -> Partial Aggregate (actual rows=1 loops=3 )
2139
- -> Parallel Append (actual rows=0 loops=N)
2141
+ Workers Launched: N
2142
+ -> Partial Aggregate (actual rows=N loops=N )
2143
+ -> Parallel Append (actual rows=N loops=N)
2140
2144
Subplans Removed: 8
2141
2145
-> Parallel Seq Scan on ab_a1_b1 (never executed)
2142
2146
Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3])))
@@ -2146,21 +2150,21 @@ select explain_parallel_append('execute ab_q5 (33, 44, 55)');
2146
2150
select explain_parallel_append('select count(*) from ab where (a = (select 1) or a = (select 3)) and b = 2');
2147
2151
explain_parallel_append
2148
2152
-------------------------------------------------------------------------
2149
- Aggregate (actual rows=1 loops=1 )
2153
+ Aggregate (actual rows=N loops=N )
2150
2154
InitPlan 1 (returns $0)
2151
- -> Result (actual rows=1 loops=1 )
2155
+ -> Result (actual rows=N loops=N )
2152
2156
InitPlan 2 (returns $1)
2153
- -> Result (actual rows=1 loops=1 )
2154
- -> Gather (actual rows=0 loops=1 )
2157
+ -> Result (actual rows=N loops=N )
2158
+ -> Gather (actual rows=N loops=N )
2155
2159
Workers Planned: 2
2156
2160
Params Evaluated: $0, $1
2157
- Workers Launched: 2
2158
- -> Parallel Append (actual rows=0 loops=N)
2159
- -> Parallel Seq Scan on ab_a1_b2 (actual rows=0 loops=N)
2161
+ Workers Launched: N
2162
+ -> Parallel Append (actual rows=N loops=N)
2163
+ -> Parallel Seq Scan on ab_a1_b2 (actual rows=N loops=N)
2160
2164
Filter: ((b = 2) AND ((a = $0) OR (a = $1)))
2161
2165
-> Parallel Seq Scan on ab_a2_b2 (never executed)
2162
2166
Filter: ((b = 2) AND ((a = $0) OR (a = $1)))
2163
- -> Parallel Seq Scan on ab_a3_b2 (actual rows=0 loops=N)
2167
+ -> Parallel Seq Scan on ab_a3_b2 (actual rows=N loops=N)
2164
2168
Filter: ((b = 2) AND ((a = $0) OR (a = $1)))
2165
2169
(16 rows)
2166
2170
@@ -2185,20 +2189,20 @@ set enable_mergejoin = 0;
2185
2189
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)');
2186
2190
explain_parallel_append
2187
2191
---------------------------------------------------------------------------------------------------
2188
- Finalize Aggregate (actual rows=1 loops=1 )
2189
- -> Gather (actual rows=2 loops=1 )
2192
+ Finalize Aggregate (actual rows=N loops=N )
2193
+ -> Gather (actual rows=N loops=N )
2190
2194
Workers Planned: 1
2191
- Workers Launched: 1
2192
- -> Partial Aggregate (actual rows=1 loops=2 )
2193
- -> Nested Loop (actual rows=0 loops=2 )
2194
- -> Parallel Seq Scan on lprt_a a (actual rows=51 loops=N)
2195
+ Workers Launched: N
2196
+ -> Partial Aggregate (actual rows=N loops=N )
2197
+ -> Nested Loop (actual rows=N loops=N )
2198
+ -> Parallel Seq Scan on lprt_a a (actual rows=N loops=N)
2195
2199
Filter: (a = ANY ('{0,0,1}'::integer[]))
2196
- -> Append (actual rows=0 loops=102 )
2197
- -> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (actual rows=0 loops=2 )
2200
+ -> Append (actual rows=N loops=N )
2201
+ -> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (actual rows=N loops=N )
2198
2202
Index Cond: (a = a.a)
2199
- -> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (actual rows=0 loops=2 )
2203
+ -> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (actual rows=N loops=N )
2200
2204
Index Cond: (a = a.a)
2201
- -> Index Scan using ab_a1_b3_a_idx on ab_a1_b3 (actual rows=0 loops=2 )
2205
+ -> Index Scan using ab_a1_b3_a_idx on ab_a1_b3 (actual rows=N loops=N )
2202
2206
Index Cond: (a = a.a)
2203
2207
-> Index Scan using ab_a2_b1_a_idx on ab_a2_b1 (never executed)
2204
2208
Index Cond: (a = a.a)
@@ -2219,20 +2223,20 @@ select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on
2219
2223
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)');
2220
2224
explain_parallel_append
2221
2225
---------------------------------------------------------------------------------------------------
2222
- Finalize Aggregate (actual rows=1 loops=1 )
2223
- -> Gather (actual rows=2 loops=1 )
2226
+ Finalize Aggregate (actual rows=N loops=N )
2227
+ -> Gather (actual rows=N loops=N )
2224
2228
Workers Planned: 1
2225
- Workers Launched: 1
2226
- -> Partial Aggregate (actual rows=1 loops=2 )
2227
- -> Nested Loop (actual rows=0 loops=2 )
2228
- -> Parallel Seq Scan on lprt_a a (actual rows=51 loops=N)
2229
+ Workers Launched: N
2230
+ -> Partial Aggregate (actual rows=N loops=N )
2231
+ -> Nested Loop (actual rows=N loops=N )
2232
+ -> Parallel Seq Scan on lprt_a a (actual rows=N loops=N)
2229
2233
Filter: (a = ANY ('{0,0,1}'::integer[]))
2230
- -> Append (actual rows=0 loops=102 )
2231
- -> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (actual rows=0 loops=2 )
2234
+ -> Append (actual rows=N loops=N )
2235
+ -> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (actual rows=N loops=N )
2232
2236
Index Cond: (a = (a.a + 0))
2233
- -> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (actual rows=0 loops=2 )
2237
+ -> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (actual rows=N loops=N )
2234
2238
Index Cond: (a = (a.a + 0))
2235
- -> Index Scan using ab_a1_b3_a_idx on ab_a1_b3 (actual rows=0 loops=2 )
2239
+ -> Index Scan using ab_a1_b3_a_idx on ab_a1_b3 (actual rows=N loops=N )
2236
2240
Index Cond: (a = (a.a + 0))
2237
2241
-> Index Scan using ab_a2_b1_a_idx on ab_a2_b1 (never executed)
2238
2242
Index Cond: (a = (a.a + 0))
@@ -2252,53 +2256,53 @@ insert into lprt_a values(3),(3);
2252
2256
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)');
2253
2257
explain_parallel_append
2254
2258
---------------------------------------------------------------------------------------------------
2255
- Finalize Aggregate (actual rows=1 loops=1 )
2256
- -> Gather (actual rows=2 loops=1 )
2259
+ Finalize Aggregate (actual rows=N loops=N )
2260
+ -> Gather (actual rows=N loops=N )
2257
2261
Workers Planned: 1
2258
- Workers Launched: 1
2259
- -> Partial Aggregate (actual rows=1 loops=2 )
2260
- -> Nested Loop (actual rows=0 loops=2 )
2261
- -> Parallel Seq Scan on lprt_a a (actual rows=52 loops=N)
2262
+ Workers Launched: N
2263
+ -> Partial Aggregate (actual rows=N loops=N )
2264
+ -> Nested Loop (actual rows=N loops=N )
2265
+ -> Parallel Seq Scan on lprt_a a (actual rows=N loops=N)
2262
2266
Filter: (a = ANY ('{1,0,3}'::integer[]))
2263
- -> Append (actual rows=0 loops=104 )
2264
- -> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (actual rows=0 loops=2 )
2267
+ -> Append (actual rows=N loops=N )
2268
+ -> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (actual rows=N loops=N )
2265
2269
Index Cond: (a = a.a)
2266
- -> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (actual rows=0 loops=2 )
2270
+ -> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (actual rows=N loops=N )
2267
2271
Index Cond: (a = a.a)
2268
- -> Index Scan using ab_a1_b3_a_idx on ab_a1_b3 (actual rows=0 loops=2 )
2272
+ -> Index Scan using ab_a1_b3_a_idx on ab_a1_b3 (actual rows=N loops=N )
2269
2273
Index Cond: (a = a.a)
2270
2274
-> Index Scan using ab_a2_b1_a_idx on ab_a2_b1 (never executed)
2271
2275
Index Cond: (a = a.a)
2272
2276
-> Index Scan using ab_a2_b2_a_idx on ab_a2_b2 (never executed)
2273
2277
Index Cond: (a = a.a)
2274
2278
-> Index Scan using ab_a2_b3_a_idx on ab_a2_b3 (never executed)
2275
2279
Index Cond: (a = a.a)
2276
- -> Index Scan using ab_a3_b1_a_idx on ab_a3_b1 (actual rows=0 loops=2 )
2280
+ -> Index Scan using ab_a3_b1_a_idx on ab_a3_b1 (actual rows=N loops=N )
2277
2281
Index Cond: (a = a.a)
2278
- -> Index Scan using ab_a3_b2_a_idx on ab_a3_b2 (actual rows=0 loops=2 )
2282
+ -> Index Scan using ab_a3_b2_a_idx on ab_a3_b2 (actual rows=N loops=N )
2279
2283
Index Cond: (a = a.a)
2280
- -> Index Scan using ab_a3_b3_a_idx on ab_a3_b3 (actual rows=0 loops=2 )
2284
+ -> Index Scan using ab_a3_b3_a_idx on ab_a3_b3 (actual rows=N loops=N )
2281
2285
Index Cond: (a = a.a)
2282
2286
(27 rows)
2283
2287
2284
2288
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)');
2285
2289
explain_parallel_append
2286
2290
---------------------------------------------------------------------------------------------------
2287
- Finalize Aggregate (actual rows=1 loops=1 )
2288
- -> Gather (actual rows=2 loops=1 )
2291
+ Finalize Aggregate (actual rows=N loops=N )
2292
+ -> Gather (actual rows=N loops=N )
2289
2293
Workers Planned: 1
2290
- Workers Launched: 1
2291
- -> Partial Aggregate (actual rows=1 loops=2 )
2292
- -> Nested Loop (actual rows=0 loops=2 )
2293
- -> Parallel Seq Scan on lprt_a a (actual rows=51 loops=N)
2294
+ Workers Launched: N
2295
+ -> Partial Aggregate (actual rows=N loops=N )
2296
+ -> Nested Loop (actual rows=N loops=N )
2297
+ -> Parallel Seq Scan on lprt_a a (actual rows=N loops=N)
2294
2298
Filter: (a = ANY ('{1,0,0}'::integer[]))
2295
2299
Rows Removed by Filter: 1
2296
- -> Append (actual rows=0 loops=102 )
2297
- -> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (actual rows=0 loops=2 )
2300
+ -> Append (actual rows=N loops=N )
2301
+ -> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (actual rows=N loops=N )
2298
2302
Index Cond: (a = a.a)
2299
- -> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (actual rows=0 loops=2 )
2303
+ -> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (actual rows=N loops=N )
2300
2304
Index Cond: (a = a.a)
2301
- -> Index Scan using ab_a1_b3_a_idx on ab_a1_b3 (actual rows=0 loops=2 )
2305
+ -> Index Scan using ab_a1_b3_a_idx on ab_a1_b3 (actual rows=N loops=N )
2302
2306
Index Cond: (a = a.a)
2303
2307
-> Index Scan using ab_a2_b1_a_idx on ab_a2_b1 (never executed)
2304
2308
Index Cond: (a = a.a)
@@ -2318,16 +2322,16 @@ delete from lprt_a where a = 1;
2318
2322
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)');
2319
2323
explain_parallel_append
2320
2324
--------------------------------------------------------------------------------------------
2321
- Finalize Aggregate (actual rows=1 loops=1 )
2322
- -> Gather (actual rows=2 loops=1 )
2325
+ Finalize Aggregate (actual rows=N loops=N )
2326
+ -> Gather (actual rows=N loops=N )
2323
2327
Workers Planned: 1
2324
- Workers Launched: 1
2325
- -> Partial Aggregate (actual rows=1 loops=2 )
2326
- -> Nested Loop (actual rows=0 loops=2 )
2327
- -> Parallel Seq Scan on lprt_a a (actual rows=50 loops=N)
2328
+ Workers Launched: N
2329
+ -> Partial Aggregate (actual rows=N loops=N )
2330
+ -> Nested Loop (actual rows=N loops=N )
2331
+ -> Parallel Seq Scan on lprt_a a (actual rows=N loops=N)
2328
2332
Filter: (a = ANY ('{1,0,0}'::integer[]))
2329
2333
Rows Removed by Filter: 1
2330
- -> Append (actual rows=0 loops=100 )
2334
+ -> Append (actual rows=N loops=N )
2331
2335
-> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (never executed)
2332
2336
Index Cond: (a = a.a)
2333
2337
-> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (never executed)
0 commit comments