OK, this one should work against CVS HEAD.
 
Dean.
> Subject: Re: [HACKERS] Auto-explain patch> From: [EMAIL PROTECTED]> To: 
> [EMAIL PROTECTED]> CC: pgsql-hackers@postgresql.org> Date: Sun, 6 Jul 2008 
> 16:42:55 +0100> > > On Thu, 2008-07-03 at 16:58 +0000, Dean Rasheed wrote:> > 
> Here is an updated version of the patch> > Dean,> > I'm getting 4 chunks fail 
> when trying to apply your patch onto CVS HEAD.> > I'm sure its just a little 
> bitrot. Can you update the patch please? > > Thanks,> > -- > Simon Riggs 
> www.2ndQuadrant.com> PostgreSQL Training, Services and Support> 
_________________________________________________________________
The John Lewis Clearance - save up to 50% with FREE delivery
http://clk.atdmt.com/UKM/go/101719806/direct/01/
*** ./doc/src/sgml/config.sgml.orig     2008-03-11 16:59:09.000000000 +0000
--- ./doc/src/sgml/config.sgml  2008-07-03 14:20:15.000000000 +0100
***************
*** 2674,2679 ****
--- 2674,2700 ----
         </listitem>
        </varlistentry>
  
+      <varlistentry id="guc-debug-explain-min-duration" 
xreflabel="debug_explain_min_duration">
+       <term><varname>debug_explain_min_duration</varname> 
(<type>integer</type>)</term>
+       <indexterm>
+        <primary><varname>debug_explain_min_duration</> configuration 
parameter</primary>
+       </indexterm>
+       <listitem>
+        <para>
+         This option, together with <xref linkend="guc-debug-explain-plan">,
+         enables logging of debug messages explaining all SQL queries which
+         run for at least the specified number of milliseconds. Setting this
+         to zero (the default) will cause all statement execution plans to be
+         explained, when <xref linkend="guc-debug-explain-plan"> is on.
+        </para>
+ 
+        <para>
+         When <xref linkend="guc-debug-explain-plan"> if off, no statements
+         are explained, and this parameter has no effect.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
       <varlistentry id="guc-silent-mode" xreflabel="silent_mode">
        <term><varname>silent_mode</varname> (<type>boolean</type>)</term>
        <indexterm>
***************
*** 2794,2799 ****
--- 2815,2822 ----
        <term><varname>debug_print_rewritten</varname> 
(<type>boolean</type>)</term>
        <term><varname>debug_print_plan</varname> (<type>boolean</type>)</term>
        <term><varname>debug_pretty_print</varname> 
(<type>boolean</type>)</term>
+       <term><anchor id="guc-debug-explain-plan" 
xreflabel="debug_explain_plan">
+        <varname>debug_explain_plan</varname> (<type>boolean</type>)</term>
        <indexterm>
         <primary><varname>debug_print_parse</> configuration 
parameter</primary>
        </indexterm>
***************
*** 2806,2811 ****
--- 2829,2837 ----
        <indexterm>
         <primary><varname>debug_pretty_print</> configuration 
parameter</primary>
        </indexterm>
+       <indexterm>
+        <primary><varname>debug_explain_plan</> configuration 
parameter</primary>
+       </indexterm>
        <listitem>
         <para>
          These parameters enable various debugging output to be emitted.
***************
*** 2813,2824 ****
          the resulting parse tree, the query rewriter output, or the
          execution plan.  <varname>debug_pretty_print</varname> indents
          these displays to produce a more readable but much longer
!         output format.  <varname>client_min_messages</varname> or
          <varname>log_min_messages</varname> must be
          <literal>DEBUG1</literal> or lower to actually send this output
          to the client or the server log, respectively.
          These parameters are off by default.
         </para>
        </listitem>
       </varlistentry>
  
--- 2839,2867 ----
          the resulting parse tree, the query rewriter output, or the
          execution plan.  <varname>debug_pretty_print</varname> indents
          these displays to produce a more readable but much longer
!         output format.  <varname>debug_explain_plan</varname> prints
!         the plan for each executed query in the same format as
!         <command>EXPLAIN ANALYZE</>. This includes queries executed from
!         within functions.  <varname>client_min_messages</varname> or
          <varname>log_min_messages</varname> must be
          <literal>DEBUG1</literal> or lower to actually send this output
          to the client or the server log, respectively.
          These parameters are off by default.
         </para>
+ 
+        <note>
+         <para>
+          The reports produced by <varname>debug_explain_plan</varname>
+          are produced at a lower level in the database, as each query
+          is executed, including queries executed from functions, so
+          the output may be more verbose that of <command>EXPLAIN ANALYZE</>
+          and the timings may differ. When this option is used together
+          with <xref linkend="guc-debug-explain-min-duration">, all queries
+          will be instrumented, but only those which run for at least the
+          specified number of milliseconds will have their execution plans
+          reported. 
+         </para>
+        </note>
        </listitem>
       </varlistentry>
  
*** ./src/backend/commands/explain.c.orig       2008-01-01 19:45:49.000000000 
+0000
--- ./src/backend/commands/explain.c    2008-06-27 12:06:19.000000000 +0100
***************
*** 39,65 ****
  /* Hook for plugins to get control in explain_get_index_name() */
  explain_get_index_name_hook_type explain_get_index_name_hook = NULL;
  
- 
- typedef struct ExplainState
- {
-       /* options */
-       bool            printTList;             /* print plan targetlists */
-       bool            printAnalyze;   /* print actual times */
-       /* other states */
-       PlannedStmt *pstmt;                     /* top of plan */
-       List       *rtable;                     /* range table */
- } ExplainState;
- 
  static void ExplainOneQuery(Query *query, ExplainStmt *stmt,
                                const char *queryString,
                                ParamListInfo params, TupOutputState *tstate);
  static void report_triggers(ResultRelInfo *rInfo, bool show_relname,
                                StringInfo buf);
- static double elapsed_time(instr_time *starttime);
- static void explain_outNode(StringInfo str,
-                               Plan *plan, PlanState *planstate,
-                               Plan *outer_plan,
-                               int indent, ExplainState *es);
  static void show_plan_tlist(Plan *plan,
                                                        StringInfo str, int 
indent, ExplainState *es);
  static void show_scan_qual(List *qual, const char *qlabel,
--- 39,49 ----
***************
*** 402,408 ****
  }
  
  /* Compute elapsed time in seconds since given timestamp */
! static double
  elapsed_time(instr_time *starttime)
  {
        instr_time      endtime;
--- 386,392 ----
  }
  
  /* Compute elapsed time in seconds since given timestamp */
! double
  elapsed_time(instr_time *starttime)
  {
        instr_time      endtime;
***************
*** 436,442 ****
   * side of a join with the current node.  This is only interesting for
   * deciphering runtime keys of an inner indexscan.
   */
! static void
  explain_outNode(StringInfo str,
                                Plan *plan, PlanState *planstate,
                                Plan *outer_plan,
--- 420,426 ----
   * side of a join with the current node.  This is only interesting for
   * deciphering runtime keys of an inner indexscan.
   */
! void
  explain_outNode(StringInfo str,
                                Plan *plan, PlanState *planstate,
                                Plan *outer_plan,
*** ./src/backend/executor/execMain.c.orig      2008-04-21 04:49:51.000000000 
+0100
--- ./src/backend/executor/execMain.c   2008-07-03 09:49:52.000000000 +0100
***************
*** 39,44 ****
--- 39,45 ----
  #include "catalog/heap.h"
  #include "catalog/namespace.h"
  #include "catalog/toasting.h"
+ #include "commands/explain.h"
  #include "commands/tablespace.h"
  #include "commands/trigger.h"
  #include "executor/execdebug.h"
***************
*** 52,57 ****
--- 53,59 ----
  #include "utils/acl.h"
  #include "utils/lsyscache.h"
  #include "utils/memutils.h"
+ #include "utils/guc.h"
  #include "utils/snapmgr.h"
  #include "utils/tqual.h"
  
***************
*** 185,190 ****
--- 187,200 ----
        }
  
        /*
+        * If we are explaining all queries, enable instrumentation.
+        * Even if we are only explaining the slow queries, we still
+        * need to instrument them all.
+        */
+       if (Debug_explain_plan)
+               queryDesc->doInstrument = true;
+ 
+       /*
         * Copy other important information into the EState
         */
        estate->es_snapshot = queryDesc->snapshot;
***************
*** 227,232 ****
--- 237,245 ----
        bool            sendTuples;
        TupleTableSlot *result;
        MemoryContext oldcontext;
+       bool            explainPlan = Debug_explain_plan;
+       instr_time      starttime;
+       double          totaltime;
  
        /* sanity checks */
        Assert(queryDesc != NULL);
***************
*** 236,241 ****
--- 249,265 ----
        Assert(estate != NULL);
  
        /*
+        * If explaining all queries, record the start time before running
+        * the query. This is not quite the same as EXPLAIN ANALYSE, which
+        * starts timing before ExecutorStart(). Here we are only timing
+        * how long the query takes to run, once initialised and also
+        * excluding any triggers (which may themselves run queries which
+        * will be instrumented separately).
+        */
+       if (explainPlan)
+               INSTR_TIME_SET_CURRENT(starttime);
+ 
+       /*
         * Switch into per-query memory context
         */
        oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
***************
*** 279,284 ****
--- 303,341 ----
  
        MemoryContextSwitchTo(oldcontext);
  
+       /*
+        * If explaining queries and this one was slow enough, log the
+        * execution plan using the same format as EXPLAIN ANALYSE
+        */
+       totaltime = elapsed_time(&starttime);
+       if (explainPlan && totaltime * 1000 >= Debug_explain_min_duration)
+       {
+               ExplainState *es;
+               StringInfoData buf;
+ 
+               es = (ExplainState *) palloc0(sizeof(ExplainState));
+ 
+               es->printTList = false;
+               es->printAnalyze = true;
+               es->pstmt = queryDesc->plannedstmt;
+               es->rtable = queryDesc->plannedstmt->rtable;
+ 
+               initStringInfo(&buf);
+               explain_outNode(&buf,
+                                               
queryDesc->plannedstmt->planTree,
+                                               queryDesc->planstate,
+                                               NULL, 0, es);
+ 
+               appendStringInfo(&buf, "Query runtime: %.3f ms",
+                                                1000.0 * totaltime);
+ 
+               ereport(DEBUG1,
+                               (errmsg("Query plan:\n%s", buf.data)));
+ 
+               pfree(buf.data);
+               pfree(es);
+       }
+ 
        return result;
  }
  
*** ./src/backend/utils/misc/guc.c.orig 2008-05-26 19:54:36.000000000 +0100
--- ./src/backend/utils/misc/guc.c      2008-07-03 09:49:30.000000000 +0100
***************
*** 194,199 ****
--- 194,201 ----
  bool          Debug_print_parse = false;
  bool          Debug_print_rewritten = false;
  bool          Debug_pretty_print = false;
+ bool          Debug_explain_plan = false;
+ int                   Debug_explain_min_duration = 0;
  
  bool          log_parser_stats = false;
  bool          log_planner_stats = false;
***************
*** 686,691 ****
--- 688,701 ----
                false, NULL, NULL
        },
        {
+               {"debug_explain_plan", PGC_USERSET, LOGGING_WHAT,
+                       gettext_noop("Explains the execution plan to server 
log."),
+                       NULL
+               },
+               &Debug_explain_plan,
+               false, NULL, NULL
+       },
+       {
                {"log_parser_stats", PGC_SUSET, STATS_MONITORING,
                        gettext_noop("Writes parser performance statistics to 
the server log."),
                        NULL
***************
*** 1567,1572 ****
--- 1577,1593 ----
        },
  
        {
+               {"debug_explain_min_duration", PGC_USERSET, LOGGING_WHEN,
+                       gettext_noop("Sets the minimum execution time above 
which "
+                                                "statements will be 
explained."),
+                       gettext_noop("0 causes all statements to be 
explained."),
+                       GUC_UNIT_MS
+               },
+               &Debug_explain_min_duration,
+               0, 0, INT_MAX / 1000, NULL, NULL
+       },
+ 
+       {
                {"log_autovacuum_min_duration", PGC_SIGHUP, LOGGING_WHAT,
                        gettext_noop("Sets the minimum execution time above 
which "
                                                 "autovacuum actions will be 
logged."),
*** ./src/backend/utils/misc/postgresql.conf.sample.orig        2008-01-30 
18:35:55.000000000 +0000
--- ./src/backend/utils/misc/postgresql.conf.sample     2008-07-03 
10:08:57.000000000 +0100
***************
*** 313,318 ****
--- 313,322 ----
                                        # and their durations, > 0 logs only
                                        # statements running at least this time.
  
+ #debug_explain_min_duration = 0               # limits the output of 
debug_explain_plan
+                                       # to queries which run for at least the
+                                       # the specified number of milliseconds.
+ 
  #silent_mode = off                    # DO NOT USE without syslog or
                                        # logging_collector
                                        # (change requires restart)
***************
*** 323,328 ****
--- 327,333 ----
  #debug_print_rewritten = off
  #debug_print_plan = off
  #debug_pretty_print = off
+ #debug_explain_plan = off
  #log_checkpoints = off
  #log_connections = off
  #log_disconnections = off
*** ./src/include/commands/explain.h.orig       2008-01-01 19:45:57.000000000 
+0000
--- ./src/include/commands/explain.h    2008-06-27 12:06:19.000000000 +0100
***************
*** 14,19 ****
--- 14,30 ----
  #define EXPLAIN_H
  
  #include "executor/executor.h"
+ #include "executor/instrument.h"
+ 
+ typedef struct ExplainState
+ {
+       /* options */
+       bool            printTList;             /* print plan targetlists */
+       bool            printAnalyze;   /* print actual times */
+       /* other states */
+       PlannedStmt *pstmt;                     /* top of plan */
+       List       *rtable;                     /* range table */
+ } ExplainState;
  
  /* Hook for plugins to get control in ExplainOneQuery() */
  typedef void (*ExplainOneQuery_hook_type) (Query *query,
***************
*** 41,44 ****
--- 52,62 ----
  extern void ExplainOnePlan(PlannedStmt *plannedstmt, ParamListInfo params,
                           ExplainStmt *stmt, TupOutputState *tstate);
  
+ extern void explain_outNode(StringInfo str,
+                               Plan *plan, PlanState *planstate,
+                               Plan *outer_plan,
+                               int indent, ExplainState *es);
+ 
+ extern double elapsed_time(instr_time *starttime);
+ 
  #endif   /* EXPLAIN_H */
*** ./src/include/utils/guc.h.orig      2008-01-01 19:45:59.000000000 +0000
--- ./src/include/utils/guc.h   2008-07-02 20:46:55.000000000 +0100
***************
*** 117,122 ****
--- 117,124 ----
  extern bool Debug_print_parse;
  extern bool Debug_print_rewritten;
  extern bool Debug_pretty_print;
+ extern bool Debug_explain_plan;
+ extern int  Debug_explain_min_duration;
  
  extern bool log_parser_stats;
  extern bool log_planner_stats;
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to