Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: postgresql-cfbot/postgresql
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 9de2cc4
Choose a base ref
...
head repository: postgresql-cfbot/postgresql
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: ed8cba1
Choose a head ref
  • 2 commits
  • 18 files changed
  • 2 contributors

Commits on Feb 24, 2025

  1. 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.
    robertmhaas authored and Commitfest Bot committed Feb 24, 2025
    Copy the full SHA
    1a1714b View commit details
  2. [CF 5501] EXPLAIN ANALYZE rows=%.f

    This branch was automatically generated by a robot using patches from an
    email thread registered at:
    
    https://commitfest.postgresql.org/patch/5501
    
    The branch will be overwritten each time a new patch version is posted to
    the thread, and also periodically to check for bitrot caused by changes
    on the master branch.
    
    Patch(es): https://www.postgresql.org/message-id/CA+TgmoazzVHn8sFOMFAEwoqBTDxKT45D7mvkyeHgqtoD2cn58Q@mail.gmail.com
    Author(s): Ilia Evdokimov
    Commitfest Bot committed Feb 24, 2025
    Copy the full SHA
    ed8cba1 View commit details
24 changes: 12 additions & 12 deletions contrib/pg_stat_statements/expected/level_tracking.out
Original file line number Diff line number Diff line change
@@ -904,16 +904,16 @@ SELECT pg_stat_statements_reset() IS NOT NULL AS t;
(1 row)

EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) SELECT 100;
QUERY PLAN
--------------------------------
Result (actual rows=1 loops=1)
QUERY PLAN
-----------------------------------
Result (actual rows=1.00 loops=1)
(1 row)

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

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

EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) SELECT 100;
QUERY PLAN
--------------------------------
Result (actual rows=1 loops=1)
QUERY PLAN
-----------------------------------
Result (actual rows=1.00 loops=1)
(1 row)

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

SELECT toplevel, calls, query FROM pg_stat_statements
60 changes: 30 additions & 30 deletions contrib/postgres_fdw/expected/postgres_fdw.out
Original file line number Diff line number Diff line change
@@ -11670,15 +11670,15 @@ SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c

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

EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF)
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;
QUERY PLAN
-----------------------------------------------------------------------------------------
Nested Loop Left Join (actual rows=1 loops=1)
QUERY PLAN
--------------------------------------------------------------------------------------------
Nested Loop Left Join (actual rows=1.00 loops=1)
Join Filter: (t1.a = async_pt.a)
Rows Removed by Join Filter: 399
InitPlan 1
-> Aggregate (actual rows=1 loops=1)
-> Append (actual rows=400 loops=1)
-> Async Foreign Scan on async_p1 async_pt_4 (actual rows=200 loops=1)
-> Async Foreign Scan on async_p2 async_pt_5 (actual rows=200 loops=1)
-> Seq Scan on local_tbl t1 (actual rows=1 loops=1)
-> Append (actual rows=400 loops=1)
-> Async Foreign Scan on async_p1 async_pt_1 (actual rows=200 loops=1)
-> Async Foreign Scan on async_p2 async_pt_2 (actual rows=200 loops=1)
-> Aggregate (actual rows=1.00 loops=1)
-> Append (actual rows=400.00 loops=1)
-> Async Foreign Scan on async_p1 async_pt_4 (actual rows=200.00 loops=1)
-> Async Foreign Scan on async_p2 async_pt_5 (actual rows=200.00 loops=1)
-> Seq Scan on local_tbl t1 (actual rows=1.00 loops=1)
-> Append (actual rows=400.00 loops=1)
-> Async Foreign Scan on async_p1 async_pt_1 (actual rows=200.00 loops=1)
-> Async Foreign Scan on async_p2 async_pt_2 (actual rows=200.00 loops=1)
(12 rows)

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;

EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF)
SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1;
QUERY PLAN
-------------------------------------------------------------------------
Limit (actual rows=1 loops=1)
-> Append (actual rows=1 loops=1)
-> Async Foreign Scan on async_p1 t1_1 (actual rows=0 loops=1)
QUERY PLAN
----------------------------------------------------------------------------
Limit (actual rows=1.00 loops=1)
-> Append (actual rows=1.00 loops=1)
-> Async Foreign Scan on async_p1 t1_1 (actual rows=0.00 loops=1)
Filter: (b === 505)
-> Async Foreign Scan on async_p2 t1_2 (actual rows=0 loops=1)
-> Async Foreign Scan on async_p2 t1_2 (actual rows=0.00 loops=1)
Filter: (b === 505)
-> Seq Scan on async_p3 t1_3 (actual rows=1 loops=1)
-> Seq Scan on async_p3 t1_3 (actual rows=1.00 loops=1)
Filter: (b === 505)
Rows Removed by Filter: 101
(9 rows)
@@ -12120,12 +12120,12 @@ DELETE FROM async_p2;
DELETE FROM async_p3;
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF)
SELECT * FROM async_pt;
QUERY PLAN
-------------------------------------------------------------------------
Append (actual rows=0 loops=1)
-> Async Foreign Scan on async_p1 async_pt_1 (actual rows=0 loops=1)
-> Async Foreign Scan on async_p2 async_pt_2 (actual rows=0 loops=1)
-> Seq Scan on async_p3 async_pt_3 (actual rows=0 loops=1)
QUERY PLAN
----------------------------------------------------------------------------
Append (actual rows=0.00 loops=1)
-> Async Foreign Scan on async_p1 async_pt_1 (actual rows=0.00 loops=1)
-> Async Foreign Scan on async_p2 async_pt_2 (actual rows=0.00 loops=1)
-> Seq Scan on async_p3 async_pt_3 (actual rows=0.00 loops=1)
(4 rows)

-- Clean up
34 changes: 6 additions & 28 deletions src/backend/commands/explain.c
Original file line number Diff line number Diff line change
@@ -1998,10 +1998,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
if (es->timing)
appendStringInfo(es->str, "time=%.3f..%.3f ", startup_ms, total_ms);

if (nloops > 1)
appendStringInfo(es->str, "rows=%.2f loops=%.0f)", rows, nloops);
else
appendStringInfo(es->str, "rows=%.0f loops=%.0f)", rows, nloops);
appendStringInfo(es->str, "rows=%.2f loops=%.0f)", rows, nloops);
}
else
{
@@ -2012,16 +2009,8 @@ ExplainNode(PlanState *planstate, List *ancestors,
ExplainPropertyFloat("Actual Total Time", "ms", total_ms,
3, es);
}
if (nloops > 1)
{
ExplainPropertyFloat("Actual Rows", NULL, rows, 2, es);
ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es);
}
else
{
ExplainPropertyFloat("Actual Rows", NULL, rows, 0, es);
ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es);
}
ExplainPropertyFloat("Actual Rows", NULL, rows, 2, es);
ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es);
}
}
else if (es->analyze)
@@ -2077,10 +2066,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
if (es->timing)
appendStringInfo(es->str, "time=%.3f..%.3f", startup_ms, total_ms);

if (nloops > 1)
appendStringInfo(es->str, "rows=%.2f loops=%.0f\n", rows, nloops);
else
appendStringInfo(es->str, "rows=%.0f loops=%.0f\n", rows, nloops);
appendStringInfo(es->str, "rows=%.2f loops=%.0f\n", rows, nloops);
}
else
{
@@ -2092,16 +2078,8 @@ ExplainNode(PlanState *planstate, List *ancestors,
total_ms, 3, es);
}

if (nloops > 1)
{
ExplainPropertyFloat("Actual Rows", NULL, rows, 2, es);
ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es);
}
else
{
ExplainPropertyFloat("Actual Rows", NULL, rows, 0, es);
ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es);
}
ExplainPropertyFloat("Actual Rows", NULL, rows, 2, es);
ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es);
}

ExplainCloseWorker(n, es);
72 changes: 36 additions & 36 deletions src/test/regress/expected/brin_multi.out
Original file line number Diff line number Diff line change
@@ -847,11 +847,11 @@ SET enable_seqscan = off;
-- make sure the ranges were built correctly and 2023-01-01 eliminates all
EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF)
SELECT * FROM brin_date_test WHERE a = '2023-01-01'::date;
QUERY PLAN
-------------------------------------------------------------------------
Bitmap Heap Scan on brin_date_test (actual rows=0 loops=1)
QUERY PLAN
----------------------------------------------------------------------------
Bitmap Heap Scan on brin_date_test (actual rows=0.00 loops=1)
Recheck Cond: (a = '2023-01-01'::date)
-> Bitmap Index Scan on brin_date_test_a_idx (actual rows=0 loops=1)
-> Bitmap Index Scan on brin_date_test_a_idx (actual rows=0.00 loops=1)
Index Cond: (a = '2023-01-01'::date)
(4 rows)

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

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

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

EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF)
SELECT * FROM brin_date_test WHERE a = '1900-01-01'::date;
QUERY PLAN
-------------------------------------------------------------------------
Bitmap Heap Scan on brin_date_test (actual rows=0 loops=1)
QUERY PLAN
----------------------------------------------------------------------------
Bitmap Heap Scan on brin_date_test (actual rows=0.00 loops=1)
Recheck Cond: (a = '1900-01-01'::date)
-> Bitmap Index Scan on brin_date_test_a_idx (actual rows=0 loops=1)
-> Bitmap Index Scan on brin_date_test_a_idx (actual rows=0.00 loops=1)
Index Cond: (a = '1900-01-01'::date)
(4 rows)

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

EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF)
SELECT * FROM brin_interval_test WHERE a = '30 years'::interval;
QUERY PLAN
-----------------------------------------------------------------------------
Bitmap Heap Scan on brin_interval_test (actual rows=0 loops=1)
QUERY PLAN
--------------------------------------------------------------------------------
Bitmap Heap Scan on brin_interval_test (actual rows=0.00 loops=1)
Recheck Cond: (a = '@ 30 years'::interval)
-> Bitmap Index Scan on brin_interval_test_a_idx (actual rows=0 loops=1)
-> Bitmap Index Scan on brin_interval_test_a_idx (actual rows=0.00 loops=1)
Index Cond: (a = '@ 30 years'::interval)
(4 rows)

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

EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF)
SELECT * FROM brin_interval_test WHERE a = '30 years'::interval;
QUERY PLAN
-----------------------------------------------------------------------------
Bitmap Heap Scan on brin_interval_test (actual rows=0 loops=1)
QUERY PLAN
--------------------------------------------------------------------------------
Bitmap Heap Scan on brin_interval_test (actual rows=0.00 loops=1)
Recheck Cond: (a = '@ 30 years'::interval)
-> Bitmap Index Scan on brin_interval_test_a_idx (actual rows=0 loops=1)
-> Bitmap Index Scan on brin_interval_test_a_idx (actual rows=0.00 loops=1)
Index Cond: (a = '@ 30 years'::interval)
(4 rows)

Loading