Greetings,

On 2010-01-15 11:37 PM +200, Marko Tiikkaja wrote:
> On 2010-11-18 5:45 PM +0200, Marko Tiikkaja wrote:
> > Here's a patch for showing in EXPLAIN ANALYZE the number of rows a plan
> > qual filtered from a node's input.
> 
> Rebased against master.

This patch looked good, in general, to me.  I added a few documentation
updates and a comment, but it's a very straight-forward patch as far as
I can tell.  Passes all regressions and my additional testing.

commit fac899f7967ce74e14a90af9ca24e1a1f5a580e7
Author: Stephen Frost <sfr...@snowman.net>
Date:   Wed Jan 19 22:14:54 2011 -0500

    Fix < & > in docs to be &lt; &gt;, as required.

commit 5fcdb75a646912b8b273703caf33dadb80122e1c
Author: Stephen Frost <sfr...@snowman.net>
Date:   Wed Jan 19 22:05:05 2011 -0500

    Update documentation for EXPLAIN ANALYZE/nfiltered
    
    This patch updates some documentation around EXPLAIN ANALYZE, whose
    output has been changed by the patch which added nfiltered to it.
    
    Also added a comment in the only place that seemed to need one.

commit 9ebb0108a217c2d3b7f815d1d902d6bdcc276104
Author: Stephen Frost <sfr...@snowman.net>
Date:   Wed Jan 19 21:33:28 2011 -0500

    Add nfiltered in EXPLAIN ANALYZE
    
    This patch add the number of rows a plan qual filtered from a node's
    input to the EXPLAIN ANALYZE output.
    
    Patch by: Marko Tiikkaja

        Thanks,

                Stephen
*** a/doc/src/sgml/ref/explain.sgml
--- b/doc/src/sgml/ref/explain.sgml
***************
*** 335,348 **** EXPLAIN (COSTS FALSE) SELECT * FROM foo WHERE i = 4;
     function:
  
  <programlisting>
! EXPLAIN SELECT sum(i) FROM foo WHERE i &lt; 10;
! 
!                              QUERY PLAN
! ---------------------------------------------------------------------
!  Aggregate  (cost=23.93..23.93 rows=1 width=4)
!    -&gt;  Index Scan using fi on foo  (cost=0.00..23.92 rows=6 width=4)
!          Index Cond: (i &lt; 10)
! (3 rows)
  </programlisting>
    </para>
  
--- 335,352 ----
     function:
  
  <programlisting>
! CREATE TABLE test (id integer primary key, bar integer, foo integer);
! 
! EXPLAIN SELECT sum(foo) FROM test WHERE id &lt; 10;
! 
!                                    QUERY PLAN
! --------------------------------------------------------------------------------
!  Aggregate  (cost=28.97..28.98 rows=1 width=4)
!    -&gt;  Bitmap Heap Scan on test  (cost=9.26..27.35 rows=647 width=4)
!          Recheck Cond: (id &lt; 10)
!          -&gt;  Bitmap Index Scan on test_pkey  (cost=0.00..9.10 rows=647 width=0)
!                Index Cond: (id &lt; 10)
! (5 rows)
  </programlisting>
    </para>
  
***************
*** 351,369 **** EXPLAIN SELECT sum(i) FROM foo WHERE i &lt; 10;
     display the execution plan for a prepared query:
  
  <programlisting>
  PREPARE query(int, int) AS SELECT sum(bar) FROM test
      WHERE id &gt; $1 AND id &lt; $2
      GROUP BY foo;
  
  EXPLAIN ANALYZE EXECUTE query(100, 200);
  
!                                                        QUERY PLAN                                                        
! -------------------------------------------------------------------------------------------------------------------------
!  HashAggregate  (cost=39.53..39.53 rows=1 width=8) (actual time=0.661..0.672 rows=7 loops=1)
!    -&gt;  Index Scan using test_pkey on test  (cost=0.00..32.97 rows=1311 width=8) (actual time=0.050..0.395 rows=99 loops=1)
!          Index Cond: ((id &gt; $1) AND (id &lt; $2))
!  Total runtime: 0.851 ms
! (4 rows)
  </programlisting>
    </para>
  
--- 355,377 ----
     display the execution plan for a prepared query:
  
  <programlisting>
+ CREATE TABLE test (id integer primary key, bar integer, foo integer);
+ 
  PREPARE query(int, int) AS SELECT sum(bar) FROM test
      WHERE id &gt; $1 AND id &lt; $2
      GROUP BY foo;
  
  EXPLAIN ANALYZE EXECUTE query(100, 200);
  
!                                                              QUERY PLAN
! ------------------------------------------------------------------------------------------------------------------------------------
!  HashAggregate  (cost=14.98..15.01 rows=2 width=8) (actual time=0.045..0.045 rows=0 filtered=0 loops=1)
!    -&gt;  Bitmap Heap Scan on test  (cost=4.35..14.93 rows=10 width=8) (actual time=0.041..0.041 rows=0 filtered=0 loops=1)
!          Recheck Cond: ((id &gt; $1) AND (id &lt; $2))
!          -&gt;  Bitmap Index Scan on test_pkey  (cost=0.00..4.35 rows=10 width=0) (actual time=0.035..0.035 rows=0 filtered=0 loops=1)
!                Index Cond: ((id &gt; $1) AND (id &lt; $2))
!  Total runtime: 0.118 ms
! (6 rows)
  </programlisting>
    </para>
  
*** a/src/backend/commands/explain.c
--- b/src/backend/commands/explain.c
***************
*** 975,992 **** ExplainNode(PlanState *planstate, List *ancestors,
  		double		startup_sec = 1000.0 * planstate->instrument->startup / nloops;
  		double		total_sec = 1000.0 * planstate->instrument->total / nloops;
  		double		rows = planstate->instrument->ntuples / nloops;
  
  		if (es->format == EXPLAIN_FORMAT_TEXT)
  		{
  			appendStringInfo(es->str,
! 							 " (actual time=%.3f..%.3f rows=%.0f loops=%.0f)",
! 							 startup_sec, total_sec, rows, nloops);
  		}
  		else
  		{
  			ExplainPropertyFloat("Actual Startup Time", startup_sec, 3, es);
  			ExplainPropertyFloat("Actual Total Time", total_sec, 3, es);
  			ExplainPropertyFloat("Actual Rows", rows, 0, es);
  			ExplainPropertyFloat("Actual Loops", nloops, 0, es);
  		}
  	}
--- 975,994 ----
  		double		startup_sec = 1000.0 * planstate->instrument->startup / nloops;
  		double		total_sec = 1000.0 * planstate->instrument->total / nloops;
  		double		rows = planstate->instrument->ntuples / nloops;
+ 		double		filtered = planstate->instrument->nfiltered / nloops;
  
  		if (es->format == EXPLAIN_FORMAT_TEXT)
  		{
  			appendStringInfo(es->str,
! 							 " (actual time=%.3f..%.3f rows=%.0f filtered=%.0f loops=%.0f)",
! 							 startup_sec, total_sec, rows, filtered, nloops);
  		}
  		else
  		{
  			ExplainPropertyFloat("Actual Startup Time", startup_sec, 3, es);
  			ExplainPropertyFloat("Actual Total Time", total_sec, 3, es);
  			ExplainPropertyFloat("Actual Rows", rows, 0, es);
+ 			ExplainPropertyFloat("Rows Filtered", rows, 0, es);
  			ExplainPropertyFloat("Actual Loops", nloops, 0, es);
  		}
  	}
***************
*** 999,1004 **** ExplainNode(PlanState *planstate, List *ancestors,
--- 1001,1007 ----
  			ExplainPropertyFloat("Actual Startup Time", 0.0, 3, es);
  			ExplainPropertyFloat("Actual Total Time", 0.0, 3, es);
  			ExplainPropertyFloat("Actual Rows", 0.0, 0, es);
+ 			ExplainPropertyFloat("Rows Filtered", 0.0, 0, es);
  			ExplainPropertyFloat("Actual Loops", 0.0, 0, es);
  		}
  	}
*** a/src/backend/executor/execScan.c
--- b/src/backend/executor/execScan.c
***************
*** 19,24 ****
--- 19,25 ----
  #include "postgres.h"
  
  #include "executor/executor.h"
+ #include "executor/instrument.h"
  #include "miscadmin.h"
  #include "utils/memutils.h"
  
***************
*** 221,226 **** ExecScan(ScanState *node,
--- 222,234 ----
  		 * Tuple fails qual, so free per-tuple memory and try again.
  		 */
  		ResetExprContext(econtext);
+ 
+ 		/*
+ 		 * Increment our counter for number of filtered-out tuples, if we were
+ 		 * asked to instrument this query.
+ 		 */
+ 		if (node->ps.instrument)
+ 			node->ps.instrument->nfiltered += 1;
  	}
  }
  
*** a/src/include/executor/instrument.h
--- b/src/include/executor/instrument.h
***************
*** 49,54 **** typedef struct Instrumentation
--- 49,55 ----
  	double		startup;		/* Total startup time (in seconds) */
  	double		total;			/* Total total time (in seconds) */
  	double		ntuples;		/* Total tuples produced */
+ 	double		nfiltered;		/* Total tuples filtered by qual */
  	double		nloops;			/* # of run cycles for this node */
  	BufferUsage bufusage;		/* Total buffer usage */
  } Instrumentation;

Attachment: signature.asc
Description: Digital signature

Reply via email to