Skip to content

Commit 1a1714b

Browse files
robertmhaasCommitfest Bot
authored and
Commitfest Bot
committed
EXPLAIN: Always use two fractional digits for row counts.
Commit ddb17e3 attempted to avoid confusing users by displaying digits after the decimal point only when nloops > 1, since it's impossible to have a fraction row count after a single iteration. However, this made the regression tests unstable since parallal queries will have nloops>1 for all nodes below the Gather or Gather Merge in normal cases, but if the workers don't start in time and the leader finishes all the work, they will suddenly have nloops==1, making it unpredictable whether the digits after the decimal point would be displayed or not. Various fixes are possible here. For example, it has previously been proposed that we should try to display the digits after the decimal point only if rows/nloops is an integer, but rows is a float so it's not theoretically an exact quantity -- precision could be lost in extreme cases. It has also been proposed that we should try to display the digits after the decimal point only if we're under some sort of construct that could potentially cause looping regardless of whether it actually does. While such ideas are not without merit, this patch adopts the much simpler solution of always display two decimal digits. If that approach stands up to scrutiny from the buildfarm and human users, it spares us the trouble of doing anything more complex; if not, we can reassess. This commit incidentally reverts 44cbba9, which should no longer be needed.
1 parent 9de2cc4 commit 1a1714b

18 files changed

+562
-588
lines changed

contrib/pg_stat_statements/expected/level_tracking.out

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -904,16 +904,16 @@ SELECT pg_stat_statements_reset() IS NOT NULL AS t;
904904
(1 row)
905905

906906
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) SELECT 100;
907-
QUERY PLAN
908-
--------------------------------
909-
Result (actual rows=1 loops=1)
907+
QUERY PLAN
908+
-----------------------------------
909+
Result (actual rows=1.00 loops=1)
910910
(1 row)
911911

912912
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF)
913913
DECLARE foocur CURSOR FOR SELECT * FROM stats_track_tab;
914-
QUERY PLAN
915-
-----------------------------------------------------
916-
Seq Scan on stats_track_tab (actual rows=0 loops=1)
914+
QUERY PLAN
915+
--------------------------------------------------------
916+
Seq Scan on stats_track_tab (actual rows=0.00 loops=1)
917917
(1 row)
918918

919919
SELECT toplevel, calls, query FROM pg_stat_statements
@@ -937,16 +937,16 @@ SELECT pg_stat_statements_reset() IS NOT NULL AS t;
937937
(1 row)
938938

939939
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) SELECT 100;
940-
QUERY PLAN
941-
--------------------------------
942-
Result (actual rows=1 loops=1)
940+
QUERY PLAN
941+
-----------------------------------
942+
Result (actual rows=1.00 loops=1)
943943
(1 row)
944944

945945
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF)
946946
DECLARE foocur CURSOR FOR SELECT * FROM stats_track_tab;
947-
QUERY PLAN
948-
-----------------------------------------------------
949-
Seq Scan on stats_track_tab (actual rows=0 loops=1)
947+
QUERY PLAN
948+
--------------------------------------------------------
949+
Seq Scan on stats_track_tab (actual rows=0.00 loops=1)
950950
(1 row)
951951

952952
SELECT toplevel, calls, query FROM pg_stat_statements

contrib/postgres_fdw/expected/postgres_fdw.out

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11670,15 +11670,15 @@ SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c
1167011670

1167111671
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF)
1167211672
SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c = 'bar';
11673-
QUERY PLAN
11674-
-------------------------------------------------------------------------------
11675-
Nested Loop (actual rows=1 loops=1)
11676-
-> Seq Scan on local_tbl (actual rows=1 loops=1)
11673+
QUERY PLAN
11674+
----------------------------------------------------------------------------------
11675+
Nested Loop (actual rows=1.00 loops=1)
11676+
-> Seq Scan on local_tbl (actual rows=1.00 loops=1)
1167711677
Filter: (c = 'bar'::text)
1167811678
Rows Removed by Filter: 1
11679-
-> Append (actual rows=1 loops=1)
11679+
-> Append (actual rows=1.00 loops=1)
1168011680
-> Async Foreign Scan on async_p1 async_pt_1 (never executed)
11681-
-> Async Foreign Scan on async_p2 async_pt_2 (actual rows=1 loops=1)
11681+
-> Async Foreign Scan on async_p2 async_pt_2 (actual rows=1.00 loops=1)
1168211682
-> Seq Scan on async_p3 async_pt_3 (never executed)
1168311683
Filter: (a = local_tbl.a)
1168411684
(9 rows)
@@ -11916,20 +11916,20 @@ SELECT * FROM local_tbl t1 LEFT JOIN (SELECT *, (SELECT count(*) FROM async_pt W
1191611916

1191711917
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF)
1191811918
SELECT * FROM local_tbl t1 LEFT JOIN (SELECT *, (SELECT count(*) FROM async_pt WHERE a < 3000) FROM async_pt WHERE a < 3000) t2 ON t1.a = t2.a;
11919-
QUERY PLAN
11920-
-----------------------------------------------------------------------------------------
11921-
Nested Loop Left Join (actual rows=1 loops=1)
11919+
QUERY PLAN
11920+
--------------------------------------------------------------------------------------------
11921+
Nested Loop Left Join (actual rows=1.00 loops=1)
1192211922
Join Filter: (t1.a = async_pt.a)
1192311923
Rows Removed by Join Filter: 399
1192411924
InitPlan 1
11925-
-> Aggregate (actual rows=1 loops=1)
11926-
-> Append (actual rows=400 loops=1)
11927-
-> Async Foreign Scan on async_p1 async_pt_4 (actual rows=200 loops=1)
11928-
-> Async Foreign Scan on async_p2 async_pt_5 (actual rows=200 loops=1)
11929-
-> Seq Scan on local_tbl t1 (actual rows=1 loops=1)
11930-
-> Append (actual rows=400 loops=1)
11931-
-> Async Foreign Scan on async_p1 async_pt_1 (actual rows=200 loops=1)
11932-
-> Async Foreign Scan on async_p2 async_pt_2 (actual rows=200 loops=1)
11925+
-> Aggregate (actual rows=1.00 loops=1)
11926+
-> Append (actual rows=400.00 loops=1)
11927+
-> Async Foreign Scan on async_p1 async_pt_4 (actual rows=200.00 loops=1)
11928+
-> Async Foreign Scan on async_p2 async_pt_5 (actual rows=200.00 loops=1)
11929+
-> Seq Scan on local_tbl t1 (actual rows=1.00 loops=1)
11930+
-> Append (actual rows=400.00 loops=1)
11931+
-> Async Foreign Scan on async_p1 async_pt_1 (actual rows=200.00 loops=1)
11932+
-> Async Foreign Scan on async_p2 async_pt_2 (actual rows=200.00 loops=1)
1193311933
(12 rows)
1193411934

1193511935
SELECT * FROM local_tbl t1 LEFT JOIN (SELECT *, (SELECT count(*) FROM async_pt WHERE a < 3000) FROM async_pt WHERE a < 3000) t2 ON t1.a = t2.a;
@@ -11960,15 +11960,15 @@ SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1;
1196011960

1196111961
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF)
1196211962
SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1;
11963-
QUERY PLAN
11964-
-------------------------------------------------------------------------
11965-
Limit (actual rows=1 loops=1)
11966-
-> Append (actual rows=1 loops=1)
11967-
-> Async Foreign Scan on async_p1 t1_1 (actual rows=0 loops=1)
11963+
QUERY PLAN
11964+
----------------------------------------------------------------------------
11965+
Limit (actual rows=1.00 loops=1)
11966+
-> Append (actual rows=1.00 loops=1)
11967+
-> Async Foreign Scan on async_p1 t1_1 (actual rows=0.00 loops=1)
1196811968
Filter: (b === 505)
11969-
-> Async Foreign Scan on async_p2 t1_2 (actual rows=0 loops=1)
11969+
-> Async Foreign Scan on async_p2 t1_2 (actual rows=0.00 loops=1)
1197011970
Filter: (b === 505)
11971-
-> Seq Scan on async_p3 t1_3 (actual rows=1 loops=1)
11971+
-> Seq Scan on async_p3 t1_3 (actual rows=1.00 loops=1)
1197211972
Filter: (b === 505)
1197311973
Rows Removed by Filter: 101
1197411974
(9 rows)
@@ -12120,12 +12120,12 @@ DELETE FROM async_p2;
1212012120
DELETE FROM async_p3;
1212112121
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF)
1212212122
SELECT * FROM async_pt;
12123-
QUERY PLAN
12124-
-------------------------------------------------------------------------
12125-
Append (actual rows=0 loops=1)
12126-
-> Async Foreign Scan on async_p1 async_pt_1 (actual rows=0 loops=1)
12127-
-> Async Foreign Scan on async_p2 async_pt_2 (actual rows=0 loops=1)
12128-
-> Seq Scan on async_p3 async_pt_3 (actual rows=0 loops=1)
12123+
QUERY PLAN
12124+
----------------------------------------------------------------------------
12125+
Append (actual rows=0.00 loops=1)
12126+
-> Async Foreign Scan on async_p1 async_pt_1 (actual rows=0.00 loops=1)
12127+
-> Async Foreign Scan on async_p2 async_pt_2 (actual rows=0.00 loops=1)
12128+
-> Seq Scan on async_p3 async_pt_3 (actual rows=0.00 loops=1)
1212912129
(4 rows)
1213012130

1213112131
-- Clean up

src/backend/commands/explain.c

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1998,10 +1998,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
19981998
if (es->timing)
19991999
appendStringInfo(es->str, "time=%.3f..%.3f ", startup_ms, total_ms);
20002000

2001-
if (nloops > 1)
2002-
appendStringInfo(es->str, "rows=%.2f loops=%.0f)", rows, nloops);
2003-
else
2004-
appendStringInfo(es->str, "rows=%.0f loops=%.0f)", rows, nloops);
2001+
appendStringInfo(es->str, "rows=%.2f loops=%.0f)", rows, nloops);
20052002
}
20062003
else
20072004
{
@@ -2012,16 +2009,8 @@ ExplainNode(PlanState *planstate, List *ancestors,
20122009
ExplainPropertyFloat("Actual Total Time", "ms", total_ms,
20132010
3, es);
20142011
}
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-
}
2012+
ExplainPropertyFloat("Actual Rows", NULL, rows, 2, es);
2013+
ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es);
20252014
}
20262015
}
20272016
else if (es->analyze)
@@ -2077,10 +2066,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
20772066
if (es->timing)
20782067
appendStringInfo(es->str, "time=%.3f..%.3f", startup_ms, total_ms);
20792068

2080-
if (nloops > 1)
2081-
appendStringInfo(es->str, "rows=%.2f loops=%.0f\n", rows, nloops);
2082-
else
2083-
appendStringInfo(es->str, "rows=%.0f loops=%.0f\n", rows, nloops);
2069+
appendStringInfo(es->str, "rows=%.2f loops=%.0f\n", rows, nloops);
20842070
}
20852071
else
20862072
{
@@ -2092,16 +2078,8 @@ ExplainNode(PlanState *planstate, List *ancestors,
20922078
total_ms, 3, es);
20932079
}
20942080

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-
}
2081+
ExplainPropertyFloat("Actual Rows", NULL, rows, 2, es);
2082+
ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es);
21052083
}
21062084

21072085
ExplainCloseWorker(n, es);

src/test/regress/expected/brin_multi.out

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -847,11 +847,11 @@ SET enable_seqscan = off;
847847
-- make sure the ranges were built correctly and 2023-01-01 eliminates all
848848
EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF)
849849
SELECT * FROM brin_date_test WHERE a = '2023-01-01'::date;
850-
QUERY PLAN
851-
-------------------------------------------------------------------------
852-
Bitmap Heap Scan on brin_date_test (actual rows=0 loops=1)
850+
QUERY PLAN
851+
----------------------------------------------------------------------------
852+
Bitmap Heap Scan on brin_date_test (actual rows=0.00 loops=1)
853853
Recheck Cond: (a = '2023-01-01'::date)
854-
-> Bitmap Index Scan on brin_date_test_a_idx (actual rows=0 loops=1)
854+
-> Bitmap Index Scan on brin_date_test_a_idx (actual rows=0.00 loops=1)
855855
Index Cond: (a = '2023-01-01'::date)
856856
(4 rows)
857857

@@ -866,21 +866,21 @@ CREATE INDEX ON brin_timestamp_test USING brin (a timestamp_minmax_multi_ops) WI
866866
SET enable_seqscan = off;
867867
EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF)
868868
SELECT * FROM brin_timestamp_test WHERE a = '2023-01-01'::timestamp;
869-
QUERY PLAN
870-
------------------------------------------------------------------------------
871-
Bitmap Heap Scan on brin_timestamp_test (actual rows=0 loops=1)
869+
QUERY PLAN
870+
---------------------------------------------------------------------------------
871+
Bitmap Heap Scan on brin_timestamp_test (actual rows=0.00 loops=1)
872872
Recheck Cond: (a = '2023-01-01 00:00:00'::timestamp without time zone)
873-
-> Bitmap Index Scan on brin_timestamp_test_a_idx (actual rows=0 loops=1)
873+
-> Bitmap Index Scan on brin_timestamp_test_a_idx (actual rows=0.00 loops=1)
874874
Index Cond: (a = '2023-01-01 00:00:00'::timestamp without time zone)
875875
(4 rows)
876876

877877
EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF)
878878
SELECT * FROM brin_timestamp_test WHERE a = '1900-01-01'::timestamp;
879-
QUERY PLAN
880-
------------------------------------------------------------------------------
881-
Bitmap Heap Scan on brin_timestamp_test (actual rows=0 loops=1)
879+
QUERY PLAN
880+
---------------------------------------------------------------------------------
881+
Bitmap Heap Scan on brin_timestamp_test (actual rows=0.00 loops=1)
882882
Recheck Cond: (a = '1900-01-01 00:00:00'::timestamp without time zone)
883-
-> Bitmap Index Scan on brin_timestamp_test_a_idx (actual rows=0 loops=1)
883+
-> Bitmap Index Scan on brin_timestamp_test_a_idx (actual rows=0.00 loops=1)
884884
Index Cond: (a = '1900-01-01 00:00:00'::timestamp without time zone)
885885
(4 rows)
886886

@@ -894,21 +894,21 @@ CREATE INDEX ON brin_date_test USING brin (a date_minmax_multi_ops) WITH (pages_
894894
SET enable_seqscan = off;
895895
EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF)
896896
SELECT * FROM brin_date_test WHERE a = '2023-01-01'::date;
897-
QUERY PLAN
898-
-------------------------------------------------------------------------
899-
Bitmap Heap Scan on brin_date_test (actual rows=0 loops=1)
897+
QUERY PLAN
898+
----------------------------------------------------------------------------
899+
Bitmap Heap Scan on brin_date_test (actual rows=0.00 loops=1)
900900
Recheck Cond: (a = '2023-01-01'::date)
901-
-> Bitmap Index Scan on brin_date_test_a_idx (actual rows=0 loops=1)
901+
-> Bitmap Index Scan on brin_date_test_a_idx (actual rows=0.00 loops=1)
902902
Index Cond: (a = '2023-01-01'::date)
903903
(4 rows)
904904

905905
EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF)
906906
SELECT * FROM brin_date_test WHERE a = '1900-01-01'::date;
907-
QUERY PLAN
908-
-------------------------------------------------------------------------
909-
Bitmap Heap Scan on brin_date_test (actual rows=0 loops=1)
907+
QUERY PLAN
908+
----------------------------------------------------------------------------
909+
Bitmap Heap Scan on brin_date_test (actual rows=0.00 loops=1)
910910
Recheck Cond: (a = '1900-01-01'::date)
911-
-> Bitmap Index Scan on brin_date_test_a_idx (actual rows=0 loops=1)
911+
-> Bitmap Index Scan on brin_date_test_a_idx (actual rows=0.00 loops=1)
912912
Index Cond: (a = '1900-01-01'::date)
913913
(4 rows)
914914

@@ -923,21 +923,21 @@ CREATE INDEX ON brin_interval_test USING brin (a interval_minmax_multi_ops) WITH
923923
SET enable_seqscan = off;
924924
EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF)
925925
SELECT * FROM brin_interval_test WHERE a = '-30 years'::interval;
926-
QUERY PLAN
927-
-----------------------------------------------------------------------------
928-
Bitmap Heap Scan on brin_interval_test (actual rows=0 loops=1)
926+
QUERY PLAN
927+
--------------------------------------------------------------------------------
928+
Bitmap Heap Scan on brin_interval_test (actual rows=0.00 loops=1)
929929
Recheck Cond: (a = '@ 30 years ago'::interval)
930-
-> Bitmap Index Scan on brin_interval_test_a_idx (actual rows=0 loops=1)
930+
-> Bitmap Index Scan on brin_interval_test_a_idx (actual rows=0.00 loops=1)
931931
Index Cond: (a = '@ 30 years ago'::interval)
932932
(4 rows)
933933

934934
EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF)
935935
SELECT * FROM brin_interval_test WHERE a = '30 years'::interval;
936-
QUERY PLAN
937-
-----------------------------------------------------------------------------
938-
Bitmap Heap Scan on brin_interval_test (actual rows=0 loops=1)
936+
QUERY PLAN
937+
--------------------------------------------------------------------------------
938+
Bitmap Heap Scan on brin_interval_test (actual rows=0.00 loops=1)
939939
Recheck Cond: (a = '@ 30 years'::interval)
940-
-> Bitmap Index Scan on brin_interval_test_a_idx (actual rows=0 loops=1)
940+
-> Bitmap Index Scan on brin_interval_test_a_idx (actual rows=0.00 loops=1)
941941
Index Cond: (a = '@ 30 years'::interval)
942942
(4 rows)
943943

@@ -951,21 +951,21 @@ CREATE INDEX ON brin_interval_test USING brin (a interval_minmax_multi_ops) WITH
951951
SET enable_seqscan = off;
952952
EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF)
953953
SELECT * FROM brin_interval_test WHERE a = '-30 years'::interval;
954-
QUERY PLAN
955-
-----------------------------------------------------------------------------
956-
Bitmap Heap Scan on brin_interval_test (actual rows=0 loops=1)
954+
QUERY PLAN
955+
--------------------------------------------------------------------------------
956+
Bitmap Heap Scan on brin_interval_test (actual rows=0.00 loops=1)
957957
Recheck Cond: (a = '@ 30 years ago'::interval)
958-
-> Bitmap Index Scan on brin_interval_test_a_idx (actual rows=0 loops=1)
958+
-> Bitmap Index Scan on brin_interval_test_a_idx (actual rows=0.00 loops=1)
959959
Index Cond: (a = '@ 30 years ago'::interval)
960960
(4 rows)
961961

962962
EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF)
963963
SELECT * FROM brin_interval_test WHERE a = '30 years'::interval;
964-
QUERY PLAN
965-
-----------------------------------------------------------------------------
966-
Bitmap Heap Scan on brin_interval_test (actual rows=0 loops=1)
964+
QUERY PLAN
965+
--------------------------------------------------------------------------------
966+
Bitmap Heap Scan on brin_interval_test (actual rows=0.00 loops=1)
967967
Recheck Cond: (a = '@ 30 years'::interval)
968-
-> Bitmap Index Scan on brin_interval_test_a_idx (actual rows=0 loops=1)
968+
-> Bitmap Index Scan on brin_interval_test_a_idx (actual rows=0.00 loops=1)
969969
Index Cond: (a = '@ 30 years'::interval)
970970
(4 rows)
971971

0 commit comments

Comments
 (0)