public inbox for [email protected]  
help / color / mirror / Atom feed
From: Ibrar Ahmed <[email protected]>
To: [email protected] <[email protected]>
Cc: Robert Haas <[email protected]>
Cc: Simon Riggs <[email protected]>
Cc: Ron Mayer <[email protected]>
Cc: Euler Taveira de Oliveira <[email protected]>
Cc: Tom Lane <[email protected]>
Subject: Re: explain analyze rows=%.0f
Date: Thu, 23 Jun 2022 00:11:12 +0500
Message-ID: <CALtqXTeQ+QCFT0DWcM5LOjnf9_Fz59+ALFejNEFwpFhW-9o4ag@mail.gmail.com> (raw)
In-Reply-To: <[email protected]>
References: <[email protected]>
	<[email protected]>
	<[email protected]>
	<[email protected]>
	<[email protected]>
	<[email protected]>

On Thu, Jun 23, 2022 at 12:01 AM Tom Lane <[email protected]> wrote:

> Robert Haas <[email protected]> writes:
> > On Jun 2, 2009, at 9:41 AM, Simon Riggs <[email protected]> wrote:
> >> You're right that the number of significant digits already exceeds the
> >> true accuracy of the computation. I think what Robert wants to see is
> >> the exact value used in the calc, so the estimates can be checked more
> >> thoroughly than is currently possible.
>
> > Bingo.
>
> Uh, the planner's estimate *is* an integer.  What was under discussion
> (I thought) was showing some fractional digits in the case where EXPLAIN
> ANALYZE is outputting a measured row count that is an average over
> multiple loops, and therefore isn't necessarily an integer.  In that
> case the measured value can be considered arbitrarily precise --- though
> I think in practice one or two fractional digits would be plenty.
>
>                         regards, tom lane
>
>
> Hi,
I was looking at the TODO list and found that the issue requires
a quick fix. Attached is a patch which shows output like this. It shows the
fraction digits in case of loops > 1

postgres=# explain analyze select * from foo;
                                                  QUERY PLAN
--------------------------------------------------------------------------------------------------------------
 Seq Scan on foo  (cost=0.00..64414.79 rows=2326379 width=8) (actual
time=0.025..277.096 rows=2344671 loops=1
 Planning Time: 0.516 ms
 Execution Time: 356.993 ms
(3 rows)

postgres=# explain analyze select * from foo where b = (select c from
bar where c = 1);
                                                         QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------
 Seq Scan on foo  (cost=8094.37..78325.11 rows=2326379 width=8)
(actual time=72.352..519.159 rows=2344671 loops=1
   Filter: (b = $1)
   InitPlan 1 (returns $1)
     ->  Gather  (cost=1000.00..8094.37 rows=1 width=4) (actual
time=0.872..72.434 rows=1 loops=1
           Workers Planned: 2
           Workers Launched: 2
           ->  Parallel Seq Scan on bar  (cost=0.00..7094.27 rows=1
width=4) (actual time=41.931..65.382 rows=0.33 loops=3)
                 Filter: (c = 1)
                 Rows Removed by Filter: 245457
 Planning Time: 0.277 ms
 Execution Time: 597.795 ms
(11 rows)



-- 
Ibrar Ahmed


Attachments:

  [application/octet-stream] explain_float_row.patch (3.0K, ../CALtqXTeQ+QCFT0DWcM5LOjnf9_Fz59+ALFejNEFwpFhW-9o4ag@mail.gmail.com/3-explain_float_row.patch)
  download | inline diff:
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 5d1f7089da..954f64b802 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -1624,13 +1624,21 @@ ExplainNode(PlanState *planstate, List *ancestors,
 		if (es->format == EXPLAIN_FORMAT_TEXT)
 		{
 			if (es->timing)
+			{
+				appendStringInfo(es->str, " (actual time=%.3f..%.3f",
+									startup_ms, total_ms);
 				appendStringInfo(es->str,
-								 " (actual time=%.3f..%.3f rows=%.0f loops=%.0f)",
-								 startup_ms, total_ms, rows, nloops);
+										nloops == 1 ? " rows=%.0f loops=%.0f" :
+										" rows=%.2f loops=%.0f)",
+										rows, nloops);
+			}
 			else
+			{
 				appendStringInfo(es->str,
-								 " (actual rows=%.0f loops=%.0f)",
-								 rows, nloops);
+								nloops == 1 ?
+								" (actual rows=%.0f loops=%.0f": " rows=%.2f loops=%.0f)",
+								rows, nloops);
+			}
 		}
 		else
 		{
@@ -1641,7 +1649,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
 				ExplainPropertyFloat("Actual Total Time", "ms", total_ms,
 									 3, es);
 			}
-			ExplainPropertyFloat("Actual Rows", NULL, rows, 0, es);
+			ExplainPropertyFloat("Actual Rows", NULL, rows, nloops == 1 ? 0 : 2, es);
 			ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es);
 		}
 	}
@@ -1690,13 +1698,20 @@ ExplainNode(PlanState *planstate, List *ancestors,
 			{
 				ExplainIndentText(es);
 				if (es->timing)
-					appendStringInfo(es->str,
-									 "actual time=%.3f..%.3f rows=%.0f loops=%.0f\n",
-									 startup_ms, total_ms, rows, nloops);
+				{
+					appendStringInfo(es->str, "actual time=%.3f..%.3f",
+										startup_ms, total_ms);
+										appendStringInfo(es->str,
+										nloops == 1 ? " rows=%.0f loops=%.0f" :
+										" rows=%.2f loops=%.0f",
+										rows, nloops);
+				}
 				else
-					appendStringInfo(es->str,
-									 "actual rows=%.0f loops=%.0f\n",
-									 rows, nloops);
+				{
+					appendStringInfo(es->str, nloops == 1 ?
+										"actual rows=%.0f loops=%.0f": " rows=%.2f loops=%.0f",
+										rows, nloops);
+				}
 			}
 			else
 			{
@@ -1707,7 +1722,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
 					ExplainPropertyFloat("Actual Total Time", "ms",
 										 total_ms, 3, es);
 				}
-				ExplainPropertyFloat("Actual Rows", NULL, rows, 0, es);
+				ExplainPropertyFloat("Actual Rows", NULL, rows,  nloops == 1 ? 0 : 2, es);
 				ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es);
 			}
 
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index ce12915592..baecc40e0c 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -1937,7 +1937,7 @@ _outPathInfo(StringInfo str, const Path *node)
 	WRITE_BOOL_FIELD(parallel_aware);
 	WRITE_BOOL_FIELD(parallel_safe);
 	WRITE_INT_FIELD(parallel_workers);
-	WRITE_FLOAT_FIELD(rows, "%.0f");
+	WRITE_FLOAT_FIELD(rows, "%.2f");
 	WRITE_FLOAT_FIELD(startup_cost, "%.2f");
 	WRITE_FLOAT_FIELD(total_cost, "%.2f");
 	WRITE_NODE_FIELD(pathkeys);


view thread (45+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]
  Subject: Re: explain analyze rows=%.0f
  In-Reply-To: <CALtqXTeQ+QCFT0DWcM5LOjnf9_Fz59+ALFejNEFwpFhW-9o4ag@mail.gmail.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox