Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit ddb17e3

Browse files
committed
Allow EXPLAIN to indicate fractional rows.
When nloops > 1, we now display two digits after the decimal point, rather than none. This is important because what we print is actually planstate->instrument->ntuples / nloops, and sometimes what you want to know is planstate->instrument->ntuples. You can estimate that by multiplying the displayed row count by the displayed nloops value, but the fact that the displayed value is rounded makes that inexact. It's still inexact even if we show these two extra decimal places, but less so. Perhaps we will agree on a way to further improve this output later, but for now this seems better than doing nothing. Author: Ibrar Ahmed <ibrar.ahmad@gmail.com> Author: Ilia Evdokimov <ilya.evdokimov@tantorlabs.com> Reviewed-by: David G. Johnston <david.g.johnston@gmail.com> Reviewed-by: Amit Kapila <amit.kapila16@gmail.com> Reviewed-by: Vignesh C <vignesh21@gmail.com> Reviewed-by: Greg Stark <stark@mit.edu> Reviewed-by: Naeem Akhter <akhternaeem@gmail.com> Reviewed-by: Hamid Akhtar <hamid.akhtar@percona.com> Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Andrei Lepikhov <a.lepikhov@postgrespro.ru> Reviewed-by: Guillaume Lelarge <guillaume@lelarge.info> Reviewed-by: Matheus Alcantara <matheusssilv97@gmail.com> Reviewed-by: Alena Rybakina <a.rybakina@postgrespro.ru> Discussion: http://postgr.es/m/603c8f070905281830g2e5419c4xad2946d149e21f9d%40mail.gmail.com
1 parent 78d3f48 commit ddb17e3

File tree

6 files changed

+113
-95
lines changed

6 files changed

+113
-95
lines changed

src/backend/commands/explain.c

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1993,14 +1993,15 @@ ExplainNode(PlanState *planstate, List *ancestors,
19931993

19941994
if (es->format == EXPLAIN_FORMAT_TEXT)
19951995
{
1996+
appendStringInfo(es->str, " (actual ");
1997+
19961998
if (es->timing)
1997-
appendStringInfo(es->str,
1998-
" (actual time=%.3f..%.3f rows=%.0f loops=%.0f)",
1999-
startup_ms, total_ms, rows, nloops);
1999+
appendStringInfo(es->str, "time=%.3f..%.3f ", startup_ms, total_ms);
2000+
2001+
if (nloops > 1)
2002+
appendStringInfo(es->str, "rows=%.2f loops=%.0f)", rows, nloops);
20002003
else
2001-
appendStringInfo(es->str,
2002-
" (actual rows=%.0f loops=%.0f)",
2003-
rows, nloops);
2004+
appendStringInfo(es->str, "rows=%.0f loops=%.0f)", rows, nloops);
20042005
}
20052006
else
20062007
{
@@ -2011,8 +2012,16 @@ ExplainNode(PlanState *planstate, List *ancestors,
20112012
ExplainPropertyFloat("Actual Total Time", "ms", total_ms,
20122013
3, es);
20132014
}
2014-
ExplainPropertyFloat("Actual Rows", NULL, rows, 0, es);
2015-
ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es);
2015+
if (nloops > 1)
2016+
{
2017+
ExplainPropertyFloat("Actual Rows", NULL, rows, 2, es);
2018+
ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es);
2019+
}
2020+
else
2021+
{
2022+
ExplainPropertyFloat("Actual Rows", NULL, rows, 0, es);
2023+
ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es);
2024+
}
20162025
}
20172026
}
20182027
else if (es->analyze)
@@ -2064,14 +2073,14 @@ ExplainNode(PlanState *planstate, List *ancestors,
20642073
if (es->format == EXPLAIN_FORMAT_TEXT)
20652074
{
20662075
ExplainIndentText(es);
2076+
appendStringInfo(es->str, "actual ");
20672077
if (es->timing)
2068-
appendStringInfo(es->str,
2069-
"actual time=%.3f..%.3f rows=%.0f loops=%.0f\n",
2070-
startup_ms, total_ms, rows, nloops);
2078+
appendStringInfo(es->str, "time=%.3f..%.3f", startup_ms, total_ms);
2079+
2080+
if (nloops > 1)
2081+
appendStringInfo(es->str, "rows=%.2f loops=%.0f\n", rows, nloops);
20712082
else
2072-
appendStringInfo(es->str,
2073-
"actual rows=%.0f loops=%.0f\n",
2074-
rows, nloops);
2083+
appendStringInfo(es->str, "rows=%.0f loops=%.0f\n", rows, nloops);
20752084
}
20762085
else
20772086
{
@@ -2082,8 +2091,17 @@ ExplainNode(PlanState *planstate, List *ancestors,
20822091
ExplainPropertyFloat("Actual Total Time", "ms",
20832092
total_ms, 3, es);
20842093
}
2085-
ExplainPropertyFloat("Actual Rows", NULL, rows, 0, es);
2086-
ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es);
2094+
2095+
if (nloops > 1)
2096+
{
2097+
ExplainPropertyFloat("Actual Rows", NULL, rows, 2, es);
2098+
ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es);
2099+
}
2100+
else
2101+
{
2102+
ExplainPropertyFloat("Actual Rows", NULL, rows, 0, es);
2103+
ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es);
2104+
}
20872105
}
20882106

20892107
ExplainCloseWorker(n, es);

src/test/regress/expected/explain.out

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ select jsonb_pretty(
528528
"Plan Rows": 0, +
529529
"Plan Width": 0, +
530530
"Total Cost": 0.0, +
531-
"Actual Rows": 0, +
531+
"Actual Rows": 0.0, +
532532
"Actual Loops": 0, +
533533
"Startup Cost": 0.0, +
534534
"Async Capable": false, +
@@ -575,7 +575,7 @@ select jsonb_pretty(
575575
"Plan Rows": 0, +
576576
"Plan Width": 0, +
577577
"Total Cost": 0.0, +
578-
"Actual Rows": 0, +
578+
"Actual Rows": 0.0, +
579579
"Actual Loops": 0, +
580580
"Startup Cost": 0.0, +
581581
"Async Capable": false, +

src/test/regress/expected/memoize.out

Lines changed: 43 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,18 @@ SELECT explain_memoize('
3535
SELECT COUNT(*),AVG(t1.unique1) FROM tenk1 t1
3636
INNER JOIN tenk1 t2 ON t1.unique1 = t2.twenty
3737
WHERE t2.unique1 < 1000;', false);
38-
explain_memoize
39-
-------------------------------------------------------------------------------------------
38+
explain_memoize
39+
----------------------------------------------------------------------------------------------
4040
Aggregate (actual rows=1 loops=N)
4141
-> Nested Loop (actual rows=1000 loops=N)
4242
-> Seq Scan on tenk1 t2 (actual rows=1000 loops=N)
4343
Filter: (unique1 < 1000)
4444
Rows Removed by Filter: 9000
45-
-> Memoize (actual rows=1 loops=N)
45+
-> Memoize (actual rows=1.00 loops=N)
4646
Cache Key: t2.twenty
4747
Cache Mode: logical
4848
Hits: 980 Misses: 20 Evictions: Zero Overflows: 0 Memory Usage: NkB
49-
-> Index Only Scan using tenk1_unique1 on tenk1 t1 (actual rows=1 loops=N)
49+
-> Index Only Scan using tenk1_unique1 on tenk1 t1 (actual rows=1.00 loops=N)
5050
Index Cond: (unique1 = t2.twenty)
5151
Heap Fetches: N
5252
(12 rows)
@@ -66,18 +66,18 @@ SELECT COUNT(*),AVG(t2.unique1) FROM tenk1 t1,
6666
LATERAL (SELECT t2.unique1 FROM tenk1 t2
6767
WHERE t1.twenty = t2.unique1 OFFSET 0) t2
6868
WHERE t1.unique1 < 1000;', false);
69-
explain_memoize
70-
-------------------------------------------------------------------------------------------
69+
explain_memoize
70+
----------------------------------------------------------------------------------------------
7171
Aggregate (actual rows=1 loops=N)
7272
-> Nested Loop (actual rows=1000 loops=N)
7373
-> Seq Scan on tenk1 t1 (actual rows=1000 loops=N)
7474
Filter: (unique1 < 1000)
7575
Rows Removed by Filter: 9000
76-
-> Memoize (actual rows=1 loops=N)
76+
-> Memoize (actual rows=1.00 loops=N)
7777
Cache Key: t1.twenty
7878
Cache Mode: binary
7979
Hits: 980 Misses: 20 Evictions: Zero Overflows: 0 Memory Usage: NkB
80-
-> Index Only Scan using tenk1_unique1 on tenk1 t2 (actual rows=1 loops=N)
80+
-> Index Only Scan using tenk1_unique1 on tenk1 t2 (actual rows=1.00 loops=N)
8181
Index Cond: (unique1 = t1.twenty)
8282
Heap Fetches: N
8383
(12 rows)
@@ -100,20 +100,20 @@ LATERAL (
100100
) t2
101101
ON t1.two = t2.two
102102
WHERE t1.unique1 < 10;', false);
103-
explain_memoize
104-
----------------------------------------------------------------------------------------------
103+
explain_memoize
104+
-------------------------------------------------------------------------------------------------
105105
Aggregate (actual rows=1 loops=N)
106106
-> Nested Loop Left Join (actual rows=20 loops=N)
107107
-> Index Scan using tenk1_unique1 on tenk1 t1 (actual rows=10 loops=N)
108108
Index Cond: (unique1 < 10)
109-
-> Memoize (actual rows=2 loops=N)
109+
-> Memoize (actual rows=2.00 loops=N)
110110
Cache Key: t1.two
111111
Cache Mode: binary
112112
Hits: 8 Misses: 2 Evictions: Zero Overflows: 0 Memory Usage: NkB
113-
-> Subquery Scan on t2 (actual rows=2 loops=N)
113+
-> Subquery Scan on t2 (actual rows=2.00 loops=N)
114114
Filter: (t1.two = t2.two)
115115
Rows Removed by Filter: 2
116-
-> Index Scan using tenk1_unique1 on tenk1 t2_1 (actual rows=4 loops=N)
116+
-> Index Scan using tenk1_unique1 on tenk1 t2_1 (actual rows=4.00 loops=N)
117117
Index Cond: (unique1 < 4)
118118
(13 rows)
119119

@@ -134,18 +134,18 @@ SELECT explain_memoize('
134134
SELECT COUNT(*), AVG(t1.twenty) FROM tenk1 t1 LEFT JOIN
135135
LATERAL (SELECT t1.two+1 AS c1, t2.unique1 AS c2 FROM tenk1 t2) s ON TRUE
136136
WHERE s.c1 = s.c2 AND t1.unique1 < 1000;', false);
137-
explain_memoize
138-
-------------------------------------------------------------------------------------------
137+
explain_memoize
138+
----------------------------------------------------------------------------------------------
139139
Aggregate (actual rows=1 loops=N)
140140
-> Nested Loop (actual rows=1000 loops=N)
141141
-> Seq Scan on tenk1 t1 (actual rows=1000 loops=N)
142142
Filter: (unique1 < 1000)
143143
Rows Removed by Filter: 9000
144-
-> Memoize (actual rows=1 loops=N)
144+
-> Memoize (actual rows=1.00 loops=N)
145145
Cache Key: (t1.two + 1)
146146
Cache Mode: binary
147147
Hits: 998 Misses: 2 Evictions: Zero Overflows: 0 Memory Usage: NkB
148-
-> Index Only Scan using tenk1_unique1 on tenk1 t2 (actual rows=1 loops=N)
148+
-> Index Only Scan using tenk1_unique1 on tenk1 t2 (actual rows=1.00 loops=N)
149149
Filter: ((t1.two + 1) = unique1)
150150
Rows Removed by Filter: 9999
151151
Heap Fetches: N
@@ -173,11 +173,11 @@ WHERE s.c1 = s.c2 AND t1.unique1 < 1000;', false);
173173
-> Seq Scan on tenk1 t1 (actual rows=1000 loops=N)
174174
Filter: (unique1 < 1000)
175175
Rows Removed by Filter: 9000
176-
-> Memoize (actual rows=1 loops=N)
176+
-> Memoize (actual rows=1.00 loops=N)
177177
Cache Key: t1.two, t1.twenty
178178
Cache Mode: binary
179179
Hits: 980 Misses: 20 Evictions: Zero Overflows: 0 Memory Usage: NkB
180-
-> Seq Scan on tenk1 t2 (actual rows=1 loops=N)
180+
-> Seq Scan on tenk1 t2 (actual rows=1.00 loops=N)
181181
Filter: ((t1.twenty = unique1) AND (t1.two = two))
182182
Rows Removed by Filter: 9999
183183
(12 rows)
@@ -207,15 +207,15 @@ VACUUM ANALYZE expr_key;
207207
SELECT explain_memoize('
208208
SELECT * FROM expr_key t1 INNER JOIN expr_key t2
209209
ON t1.x = t2.t::numeric AND t1.t::numeric = t2.x;', false);
210-
explain_memoize
211-
-------------------------------------------------------------------------------------------
210+
explain_memoize
211+
----------------------------------------------------------------------------------------------
212212
Nested Loop (actual rows=80 loops=N)
213213
-> Seq Scan on expr_key t1 (actual rows=40 loops=N)
214-
-> Memoize (actual rows=2 loops=N)
214+
-> Memoize (actual rows=2.00 loops=N)
215215
Cache Key: t1.x, (t1.t)::numeric
216216
Cache Mode: logical
217217
Hits: 20 Misses: 20 Evictions: Zero Overflows: 0 Memory Usage: NkB
218-
-> Index Only Scan using expr_key_idx_x_t on expr_key t2 (actual rows=2 loops=N)
218+
-> Index Only Scan using expr_key_idx_x_t on expr_key t2 (actual rows=2.00 loops=N)
219219
Index Cond: (x = (t1.t)::numeric)
220220
Filter: (t1.x = (t)::numeric)
221221
Heap Fetches: N
@@ -232,18 +232,18 @@ SELECT explain_memoize('
232232
SELECT COUNT(*),AVG(t1.unique1) FROM tenk1 t1
233233
INNER JOIN tenk1 t2 ON t1.unique1 = t2.thousand
234234
WHERE t2.unique1 < 1200;', true);
235-
explain_memoize
236-
-------------------------------------------------------------------------------------------
235+
explain_memoize
236+
----------------------------------------------------------------------------------------------
237237
Aggregate (actual rows=1 loops=N)
238238
-> Nested Loop (actual rows=1200 loops=N)
239239
-> Seq Scan on tenk1 t2 (actual rows=1200 loops=N)
240240
Filter: (unique1 < 1200)
241241
Rows Removed by Filter: 8800
242-
-> Memoize (actual rows=1 loops=N)
242+
-> Memoize (actual rows=1.00 loops=N)
243243
Cache Key: t2.thousand
244244
Cache Mode: logical
245245
Hits: N Misses: N Evictions: N Overflows: 0 Memory Usage: NkB
246-
-> Index Only Scan using tenk1_unique1 on tenk1 t1 (actual rows=1 loops=N)
246+
-> Index Only Scan using tenk1_unique1 on tenk1 t1 (actual rows=1.00 loops=N)
247247
Index Cond: (unique1 = t2.thousand)
248248
Heap Fetches: N
249249
(12 rows)
@@ -261,7 +261,7 @@ SELECT * FROM flt f1 INNER JOIN flt f2 ON f1.f = f2.f;', false);
261261
Nested Loop (actual rows=4 loops=N)
262262
-> Index Only Scan using flt_f_idx on flt f1 (actual rows=2 loops=N)
263263
Heap Fetches: N
264-
-> Memoize (actual rows=2 loops=N)
264+
-> Memoize (actual rows=2.00 loops=N)
265265
Cache Key: f1.f
266266
Cache Mode: logical
267267
Hits: 1 Misses: 1 Evictions: Zero Overflows: 0 Memory Usage: NkB
@@ -273,16 +273,16 @@ SELECT * FROM flt f1 INNER JOIN flt f2 ON f1.f = f2.f;', false);
273273
-- Ensure memoize operates in binary mode
274274
SELECT explain_memoize('
275275
SELECT * FROM flt f1 INNER JOIN flt f2 ON f1.f >= f2.f;', false);
276-
explain_memoize
277-
-------------------------------------------------------------------------------
276+
explain_memoize
277+
----------------------------------------------------------------------------------
278278
Nested Loop (actual rows=4 loops=N)
279279
-> Index Only Scan using flt_f_idx on flt f1 (actual rows=2 loops=N)
280280
Heap Fetches: N
281-
-> Memoize (actual rows=2 loops=N)
281+
-> Memoize (actual rows=2.00 loops=N)
282282
Cache Key: f1.f
283283
Cache Mode: binary
284284
Hits: 0 Misses: 2 Evictions: Zero Overflows: 0 Memory Usage: NkB
285-
-> Index Only Scan using flt_f_idx on flt f2 (actual rows=2 loops=N)
285+
-> Index Only Scan using flt_f_idx on flt f2 (actual rows=2.00 loops=N)
286286
Index Cond: (f <= f1.f)
287287
Heap Fetches: N
288288
(10 rows)
@@ -300,32 +300,32 @@ ANALYZE strtest;
300300
-- Ensure we get 3 hits and 3 misses
301301
SELECT explain_memoize('
302302
SELECT * FROM strtest s1 INNER JOIN strtest s2 ON s1.n >= s2.n;', false);
303-
explain_memoize
304-
----------------------------------------------------------------------------------
303+
explain_memoize
304+
-------------------------------------------------------------------------------------
305305
Nested Loop (actual rows=24 loops=N)
306306
-> Seq Scan on strtest s1 (actual rows=6 loops=N)
307307
Disabled: true
308-
-> Memoize (actual rows=4 loops=N)
308+
-> Memoize (actual rows=4.00 loops=N)
309309
Cache Key: s1.n
310310
Cache Mode: binary
311311
Hits: 3 Misses: 3 Evictions: Zero Overflows: 0 Memory Usage: NkB
312-
-> Index Scan using strtest_n_idx on strtest s2 (actual rows=4 loops=N)
312+
-> Index Scan using strtest_n_idx on strtest s2 (actual rows=4.00 loops=N)
313313
Index Cond: (n <= s1.n)
314314
(9 rows)
315315

316316
-- Ensure we get 3 hits and 3 misses
317317
SELECT explain_memoize('
318318
SELECT * FROM strtest s1 INNER JOIN strtest s2 ON s1.t >= s2.t;', false);
319-
explain_memoize
320-
----------------------------------------------------------------------------------
319+
explain_memoize
320+
-------------------------------------------------------------------------------------
321321
Nested Loop (actual rows=24 loops=N)
322322
-> Seq Scan on strtest s1 (actual rows=6 loops=N)
323323
Disabled: true
324-
-> Memoize (actual rows=4 loops=N)
324+
-> Memoize (actual rows=4.00 loops=N)
325325
Cache Key: s1.t
326326
Cache Mode: binary
327327
Hits: 3 Misses: 3 Evictions: Zero Overflows: 0 Memory Usage: NkB
328-
-> Index Scan using strtest_t_idx on strtest s2 (actual rows=4 loops=N)
328+
-> Index Scan using strtest_t_idx on strtest s2 (actual rows=4.00 loops=N)
329329
Index Cond: (t <= s1.t)
330330
(9 rows)
331331

@@ -348,7 +348,7 @@ SELECT * FROM prt t1 INNER JOIN prt t2 ON t1.a = t2.a;', false);
348348
-> Nested Loop (actual rows=16 loops=N)
349349
-> Index Only Scan using iprt_p1_a on prt_p1 t1_1 (actual rows=4 loops=N)
350350
Heap Fetches: N
351-
-> Memoize (actual rows=4 loops=N)
351+
-> Memoize (actual rows=4.00 loops=N)
352352
Cache Key: t1_1.a
353353
Cache Mode: logical
354354
Hits: 3 Misses: 1 Evictions: Zero Overflows: 0 Memory Usage: NkB
@@ -358,7 +358,7 @@ SELECT * FROM prt t1 INNER JOIN prt t2 ON t1.a = t2.a;', false);
358358
-> Nested Loop (actual rows=16 loops=N)
359359
-> Index Only Scan using iprt_p2_a on prt_p2 t1_2 (actual rows=4 loops=N)
360360
Heap Fetches: N
361-
-> Memoize (actual rows=4 loops=N)
361+
-> Memoize (actual rows=4.00 loops=N)
362362
Cache Key: t1_2.a
363363
Cache Mode: logical
364364
Hits: 3 Misses: 1 Evictions: Zero Overflows: 0 Memory Usage: NkB
@@ -378,7 +378,7 @@ ON t1.a = t2.a;', false);
378378
Nested Loop (actual rows=16 loops=N)
379379
-> Index Only Scan using iprt_p1_a on prt_p1 t1 (actual rows=4 loops=N)
380380
Heap Fetches: N
381-
-> Memoize (actual rows=4 loops=N)
381+
-> Memoize (actual rows=4.00 loops=N)
382382
Cache Key: t1.a
383383
Cache Mode: logical
384384
Hits: 3 Misses: 1 Evictions: Zero Overflows: 0 Memory Usage: NkB

0 commit comments

Comments
 (0)