OSDN Git Service

Add documentation
authorKyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Fri, 3 Apr 2015 05:36:42 +0000 (14:36 +0900)
committerKyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Mon, 6 Apr 2015 08:13:52 +0000 (17:13 +0900)
doc/index.html [new file with mode: 0644]
doc/stylesheet.css [new file with mode: 0644]
pg_store_plans.c
pgsp_json_text.c

diff --git a/doc/index.html b/doc/index.html
new file mode 100644 (file)
index 0000000..1ee4398
--- /dev/null
@@ -0,0 +1,571 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<HTML>
+<HEAD>
+<TITLE>pg_store_plans</TITLE>
+<LINK
+REL="STYLESHEET"
+TYPE="text/css"
+HREF="stylesheet.css">
+<META
+HTTP-EQUIV="Content-Type"
+CONTENT="text/html; charset=ISO-8859-1">
+</HEAD>
+
+<BODY>
+<DIV CLASS="SECT1">
+<H1 CLASS="SECT1">
+<A NAME="PGSTOREPLANS">pg_store_plans</A>
+</H1>
+<P>The <TT CLASS="FILENAME">pg_store_plans</TT> module provides a
+  means for tracking execution plan statistics of all SQL statements
+  executed by a server.
+</P>
+
+<P>The module must be loaded by
+   adding <TT CLASS="LITERAL">pg_store_plans</TT> to
+  <A HREF="http://www.postgresql.org/docs/current/static/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES">shared_preload_libraries</A> in
+  <TT CLASS="FILENAME">postgresql.conf</TT>, because it requires
+  additional shared memory.  This means that a server restart is
+  required to add or remove the module.
+</P>
+<DIV CLASS="SECT2">
+<H2 CLASS="SECT2">1. The <TT CLASS="STRUCTNAME">pg_store_plans</TT>
+View</H2>
+
+<P>The statistics gathered by the module are available via a system
+   view named <TT CLASS="STRUCTNAME">pg_store_plans</TT>.  This view
+   contains one row for each distinct set of database ID, user ID and
+   query ID.  The columns of the view are described in
+   <A HREF="#PGSTOREPLANS-COLUMNS">Table 1</A>.
+</P>
+
+<DIV CLASS="TABLE">
+<A NAME="PGSTOREPLANS-COLUMNS"></A>
+<P><B>Table 1. <TT>pg_store_plans</TT> Columns</B>
+</P>
+<TABLE BORDER="1" CLASS="CALSTABLE" >
+<COL><COL><COL><COL>
+<THEAD><TR><TH>Name</TH><TH>Type</TH><TH>References</TH>
+       <TH>Description</TH></TR>
+</THEAD>
+<TBODY>
+<TR><TD><TT CLASS="STRUCTFIELD">userid</TT></TD>
+    <TD><TT CLASS="TYPE">oid</TT></TD>
+    <TD><A HREF="http://www.postgresql.org/docs/current/static/catalog-pg-authid.html">
+        <TT CLASS="STRUCTNAME">pg_authid</TT><TT CLASS="LITERAL"></A>.oid</TT></TD>
+    <TD>OID of user who executed the statement</TD></TR>
+<TR><TD><TT CLASS="STRUCTFIELD">dbid</TT></TD>
+    <TD><TT CLASS="TYPE">oid</TT></TD>
+    <TD><A HREF="http://www.postgresql.org/docs/current/static/catalog-pg-database.html">
+        <TT CLASS="STRUCTNAME">pg_database</TT></A><TT CLASS="LITERAL">.oid</TT></TD>
+    <TD>OID of database in which the statement was executed</TD></TR>
+<TR><TD><TT CLASS="STRUCTFIELD">queryid</TT></TD>
+    <TD><TT CLASS="TYPE">bigint</TT></TD>
+    <TD>&nbsp;</TD>
+    <TD>Internal hash code, computed from the statement's query string.</TD>
+    </TR>
+<TR><TD><TT CLASS="STRUCTFIELD">planid</TT></TD>
+    <TD><TT CLASS="TYPE">bigint</TT></TD>
+    <TD>&nbsp;</TD>
+    <TD>Internal hash code, computed from the statement's plan
+    representation.</TD>
+    </TR>
+<TR><TD><TT CLASS="STRUCTFIELD">queryid_stat_statements</TT></TD>
+    <TD><TT CLASS="TYPE">bigint</TT></TD>
+    <TD>&nbsp;</TD>
+    <TD>A copy of pg_stat_statements' query hash code. This is
+    available only when pg_stat_statements is installed.</TD>
+    </TR>
+<TR><TD><TT CLASS="STRUCTFIELD">plan</TT></TD>
+    <TD><TT CLASS="TYPE">text</TT></TD>
+    <TD>&nbsp;</TD>
+    <TD>Text of a representative plan. The format is specified by the
+    configuration
+    parameter <TT CLASS="VARNAME">pg_store_plans.plan_format.</TT></TD>
+    </TR>
+<TR><TD><TT CLASS="STRUCTFIELD">calls</TT></TD>
+    <TD><TT CLASS="TYPE">bigint</TT></TD>
+    <TD>&nbsp;</TD>
+    <TD>Number of times executed</TD>
+    </TR>
+<TR><TD><TT CLASS="STRUCTFIELD">total_time</TT></TD>
+    <TD><TT CLASS="TYPE">double precision</TT></TD>
+    <TD>&nbsp;</TD>
+    <TD>Total time spent in the statement using the plan, in milliseconds</TD>
+    </TR>
+<TR><TD><TT CLASS="STRUCTFIELD">rows</TT></TD>
+    <TD><TT CLASS="TYPE">bigint</TT></TD>
+    <TD>&nbsp;</TD>
+    <TD>Total number of rows retrieved or affected by the statement
+    using the plan</TD>
+    </TR>
+<TR><TD><TT CLASS="STRUCTFIELD">shared_blks_hit</TT></TD>
+    <TD><TT CLASS="TYPE">bigint</TT></TD>
+    <TD>&nbsp;</TD>
+    <TD>Total number of shared block cache hits by the statement using
+    the plan</TD>
+    </TR>
+<TR><TD><TT CLASS="STRUCTFIELD">shared_blks_read</TT></TD>
+    <TD><TT CLASS="TYPE">bigint</TT></TD>
+    <TD>&nbsp;</TD>
+    <TD>Total number of shared blocks read by the statement using the
+    plan</TD>
+    </TR>
+<TR><TD><TT CLASS="STRUCTFIELD">shared_blks_dirtied</TT></TD>
+    <TD><TT CLASS="TYPE">bigint</TT></TD>
+    <TD>&nbsp;</TD>
+    <TD>Total number of shared blocks dirtied by the statement using
+    the plan</TD>
+    </TR>
+<TR><TD><TT CLASS="STRUCTFIELD">shared_blks_written</TT></TD>
+    <TD><TT CLASS="TYPE">bigint</TT></TD>
+    <TD>&nbsp;</TD>
+    <TD>Total number of shared blocks written by the statement using
+    the plan</TD>
+    </TR>
+<TR><TD><TT CLASS="STRUCTFIELD">local_blks_hit</TT></TD>
+    <TD><TT CLASS="TYPE">bigint</TT></TD>
+    <TD>&nbsp;</TD>
+    <TD>Total number of local block cache hits by the statement using
+    the plan</TD>
+    </TR>
+<TR><TD><TT CLASS="STRUCTFIELD">local_blks_read</TT></TD>
+    <TD><TT CLASS="TYPE">bigint</TT></TD>
+    <TD>&nbsp;</TD>
+    <TD>Total number of local blocks read by the statement using the
+    plan</TD>
+    </TR>
+<TR><TD><TT CLASS="STRUCTFIELD">local_blks_dirtied</TT></TD>
+    <TD><TT CLASS="TYPE">bigint</TT></TD><TD>&nbsp;</TD>
+    <TD>Total number of local blocks dirtied by the statement using
+    the plan</TD>
+    </TR>
+<TR><TD><TT CLASS="STRUCTFIELD">local_blks_written</TT></TD>
+    <TD><TT CLASS="TYPE">bigint</TT></TD>
+    <TD>&nbsp;</TD>
+    <TD>Total number of local blocks written by the statement using
+    the plan</TD>
+    </TR>
+<TR><TD><TT CLASS="STRUCTFIELD">temp_blks_read</TT></TD>
+    <TD><TT CLASS="TYPE">bigint</TT></TD>
+    <TD>&nbsp;</TD>
+    <TD>Total number of temp blocks read by the statement using the
+    plan</TD>
+    </TR>
+<TR><TD><TT CLASS="STRUCTFIELD">temp_blks_written</TT></TD>
+    <TD><TT CLASS="TYPE">bigint</TT></TD>
+    <TD>&nbsp;</TD>
+    <TD>Total number of temp blocks written by the statement using the
+    plan</TD>
+    </TR>
+<TR><TD><TT CLASS="STRUCTFIELD">blk_read_time</TT></TD>
+    <TD><TT CLASS="TYPE">double precision</TT></TD>
+    <TD>&nbsp;</TD>
+
+    <TD>Total time the statement using the plan spent reading blocks, in milliseconds (if <A HREF="http://www.postgresql.org/docs/current/static/runtime-config-statistics.html#GUC-TRACK-IO-TIMING">track_io_timing</A> is enabled, otherwise zero)</TD>
+    </TR>
+<TR><TD><TT CLASS="STRUCTFIELD">blk_write_time</TT></TD>
+    <TD><TT CLASS="TYPE">double precision</TT></TD>
+    <TD>&nbsp;</TD>
+
+    <TD>Total time the statement using the plan spent writing blocks, in milliseconds (if <A HREF="http://www.postgresql.org/docs/current/static/runtime-config-statistics.html#GUC-TRACK-IO-TIMING">track_io_timing</A> is enabled, otherwise zero)</TD>
+    </TR>
+<TR><TD><TT CLASS="STRUCTFIELD">first_call</TT></TD>
+    <TD><TT CLASS="TYPE">timestamp with time zone</TT></TD>
+    <TD>&nbsp;</TD>
+    <TD>Timestamp for the least recently call of the query using this
+    plan.</TD>
+    </TR>
+<TR><TD><TT CLASS="STRUCTFIELD">last_call</TT></TD>
+    <TD><TT CLASS="TYPE">timestamp with time zone</TT></TD>
+    <TD>&nbsp;</TD>
+    <TD>Timestamp for the most recently call of the query using this
+    plan.</TD>
+    </TR>
+</TBODY>
+</TABLE>
+</DIV>
+
+<P>This view, and the functions <CODE CLASS="FUNCTION">pg_store_plans_reset
+  </CODE> and <CODE CLASS="FUNCTION">pg_store_plans</CODE> and other
+  auxiliary functions, are available only in databases where
+  the <TT CLASS="LITERAL">pg_store_plans</TT> is installed
+  by <TT CLASS="LITERAL">CREATE EXTENSION</TT>.  However,
+  statistics are tracked across all databases of the server whenever
+  the <TT CLASS="FILENAME">pg_store_plans</TT> module is loaded onto
+  the server, regardless of presence of the view.
+</P>
+
+<P>For security reasons, non-superusers are not allowed to see the
+  plan representation, queryid or planid for the queries executed by
+  other users.
+</P>
+
+<P> 
+
+<TT CLASS="VARNAME">queryid</TT> is calculated to identify the source
+query similary to <TT CLASS="structname">pg_stat_statements</TT> but
+in a different algorithm.  <TT CLASS="VARNAME">plan</TT> is
+calculated in a similar way. Two plans are considered the same if they
+are seemingly equivalent except for the values of literal constants
+or fluctuating values such like costs or measured time. </P>
+
+<P> For PostgreSQL 9.4 or later, you can find the corresponding query
+for a <TT CLASS="structname">pg_store_plans</TT> entry
+in <TT CLASS="structname">pg_stat_statements</TT> by joining using
+<TT CLASS="structname">queryid_stat_statements</TT>. Otherwise it is
+identified by using <TT CLASS="VARNAME">queryid</TT>
+and <CODE CLASS="FUNCTION">pg_store_plans_hash_query</CODE >, like
+following.
+
+</P>
+<P>
+<PRE CLASS="SCREEN">SELECT s.query, p.plan FROM pg_store_plans p JOIN pg_stat_statements s ON (pg_store_plans_hash_query(s.query)) = p.queryid;</PRE>
+</P>
+
+<P> However plan id is calculated ignoring fluctuating values, the
+values for most recent execution are still displayed
+in <TT CLASS="STRUCTNAME">pg_store_plans.plan</TT>.
+</P>
+<P> In some cases, <TT CLASS="STRUCTNAME">pg_stat_statements</TT>
+  merges semantically equivalent queries which are considered
+  different by
+<TT CLASS="STRUCTNAME">pg_stat_statements</TT>. In the cases
+correspondent in <TT CLASS="STRUCTNAME">pg_stat_statements</TT> might
+not be found, but there is a small chance that this happenes. In
+contrast, there also is a small chance that some queries might be
+regarded as equivalent and merged into one entry
+in <TT CLASS="STRUCTNAME">pg_store_plans</TT> but differentiated
+in <TT CLASS="STRUCTNAME">pg_stat_statements</TT> mainly for utility
+statements.
+</P>
+
+<P><TT CLASS="STRUCTNAME">pg_store_plans</TT>
+   and <TT CLASS="STRUCTNAME">pg_stat_statements</TT> maintain thier
+   entries individually so there is certain unavoidable chance
+   especially for entries with low execution frequency that no
+   correspondent is found.
+</P>
+<P><TT CLASS="STRUCTFIELD">queryid_stat_statements</TT> has the same
+   restriction to <TT CLASS="STRUCTNAME">pg_stat_statements</TT> in
+   terms of stability. Although <TT CLASS="STRUCTFIELD">queryid</TT>
+   and <TT CLASS="STRUCTFIELD">planid</TT>
+   in <TT CLASS="STRUCTNAME">pg_store_plans</TT> doesn't have such a
+   restriction, assuming long-term stability is also discouraged.
+  </P>
+</DIV>
+<DIV CLASS="SECT2">
+<H2 CLASS="SECT2">
+<A NAME="Functions">2. Functions</A>
+</H2>
+<DIV CLASS="VARIABLELIST">
+<DL> <DT> <CODE CLASS="FUNCTION">pg_store_plans_reset() returns void</CODE>
+</DT>
+<DD>
+<P>
+ <CODE CLASS="FUNCTION">pg_store_plans_reset</CODE> discards all
+      statistics gathered so far
+      by <TT CLASS="FILENAME">pg_store_plans</TT>.  By default, only
+      superusers can execute this function.
+     </P>
+</DD>
+<DT>
+<CODE CLASS="FUNCTION">pg_store_plans(showtext boolean) returns setof
+record</CODE>
+</DT>
+<DD>
+<P> The <TT CLASS="STRUCTNAME">pg_store_plans</TT> view is defined in
+      terms of a function also
+      named <CODE CLASS="FUNCTION">pg_store_plans</CODE >.
+</P>
+</DD>
+<DT>
+<CODE CLASS="FUNCTION">pg_store_hash_query(query text) returns oid</CODE>
+</DT>
+<DD>
+<P> This function calculates hash value of a query text. The same
+      algorithm is used to
+      calculate <TT CLASS="STRUCTFIELD">queryid</TT>
+      in <TT CLASS="STRUCTNAME">pg_store_plans</TT> so this function
+      is usable to join
+      with <TT CLASS="STRUCTNAME">pg_store_plans</TT>.
+     </P>
+</DD>
+<DT>
+<CODE CLASS="FUNCTION">pg_store_plans_textplan(query text) returns text</CODE>
+</DT>
+<DD>
+<P> This function generates a ordinary text representation from raw
+      representation of <TT CLASS="STRUCTFIELD">plan</TT>
+      in <TT CLASS="STRUCTNAME">pg_store_plans</TT>, which is shown
+      there when <TT CLASS="VARNAME">pg_store_plans.plan_formats</TT>
+      = 'raw'. Since the result plan text is generated from json
+      representation, it might be slightly different from what you
+      will get directly from 'EXPLAIN' commnand.
+     </P>
+</DD>
+<DT>
+<CODE CLASS="FUNCTION">pg_store_plans_jsonplan(query text) returns text</CODE>
+</DT>
+<DD>
+<P> This function infaltes a "short format json plan" or "raw format"
+    into normal json format. Short format json is internal format
+    for <TT CLASS="STRUCTFIELD">plan</TT>
+    in <TT CLASS="STRUCTNAME">pg_store_plans</TT>, which is shown
+    there when <TT CLASS="VARNAME">pg_store_plans.plan_formats</TT> =
+    'raw'.
+     </P>
+</DD>
+<DT>
+<CODE CLASS="FUNCTION">pg_store_plans_xmlplan(query text) returns text</CODE>
+</DT>
+<DD>
+<P> This function generates a XML representation from raw
+      representation of <TT CLASS="STRUCTFIELD">plan</TT>
+      in <TT CLASS="STRUCTNAME">pg_store_plans</TT>, which is shown
+      there when <TT CLASS="VARNAME">pg_store_plans.plan_formats</TT>
+      = 'raw'.
+     </P>
+</DD>
+<DT>
+<CODE CLASS="FUNCTION">pg_store_plans_yamlplan(query text) returns text</CODE>
+</DT>
+<DD>
+<P> This function generates a YAML representation from raw
+      representation of <TT CLASS="STRUCTFIELD">plan</TT>
+      in <TT CLASS="STRUCTNAME">pg_store_plans</TT>, which is shown
+      there when <TT CLASS="VARNAME">pg_store_plans.plan_formats</TT>
+      = 'raw'.
+     </P>
+</DD>
+</DL>
+</DIV>
+</DIV>
+<DIV CLASS="SECT2">
+<H2 CLASS="SECT2">
+<ANAME="Config">3. Configuration Parameters</A>
+</H2>
+<P>
+</P>
+<DIV CLASS="VARIABLELIST">
+<DL>
+<DT>
+<TT CLASS="VARNAME">pg_store_plans.max</TT>
+  (<TT CLASS="TYPE">integer</TT>)</DT>
+<DD>
+<P> <TT CLASS="VARNAME">pg_store_plans.max</TT> is the maximum number
+of plans tracked by the module (i.e., the maximum number of rows in
+the <TT CLASS="STRUCTNAME">pg_store_plans</TT> view).  If more
+distinct plans than that are observed, information about the
+least-executed plan is discarded.  The default value is 1000.  This
+parameter can only be set at server start.
+     </P>
+</DD>
+<DT>
+<TT CLASS="VARNAME">pg_store_plans.track</TT>
+ (<TT CLASS="TYPE">enum</TT>)
+</DT>
+<DD>
+<P> Similar to <TT CLASS="STRUCTNAME">pg_stat_statements</TT>,
+      <TT CLASS="VARNAME">pg_store_plans.track</TT> controls which
+      statements are counted by the module.
+      Specify <TT CLASS="LITERAL">top</TT> to track top-level
+      statements (those issued directly by
+      clients), <TT CLASS="LITERAL">all</TT> to also track nested
+      statements (such as statements invoked within functions),
+      or <TT CLASS="LITERAL">none</TT> to disable statement
+      statistics collection.  The default value
+      is <TT CLASS="LITERAL">top</TT>.  Only superusers can change
+      this setting.
+     </P>
+</DD>
+<DT>
+<TT CLASS="VARNAME">pg_store_plans.plan_format</TT>
+ (<TT CLASS="TYPE">enum</TT>)
+</DT>
+<DD>
+<P> <TT CLASS="VARNAME">pg_store_plans.plan_format</TT> controls the
+  format of <TT CLASS="STRUCTFIELD">plans</TT>
+  in <TT CLASS="STRUCTNAME">pg_store_plans</TT>. <TT CLASS="LITERAL">text</TT>
+  is the default value and to show in ordinary text
+  representation, <TT CLASS="LITERAL">json</TT>, <TT CLASS="LITERAL">xml</TT>
+  and <TT CLASS="LITERAL">yaml</TT> to show in corresponding format.
+  <TT CLASS="LITERAL">raw</TT> to get internal representation which
+  can be fed to <CODE CLASS="FUNCTION">pg_store_plans_*plan</CODE >
+  functions.
+</P>
+</DD>
+<DT>
+<TT CLASS="VARNAME">pg_store_plans.min_duration</TT>
+  (<TT CLASS="TYPE">integer</TT>)
+</DT>
+<DD>
+<P> <TT CLASS="VARNAME">pg_store_plans.min_duration</TT> is the
+  minumum statement execution time, in milliseconds, that will cause the
+  statement's plan to be logged. Setting this to zero (the default) logs
+  all plans. Only superuses can change this setting.
+</P>
+</DD>
+<DT>
+<TT CLASS="VARNAME">pg_store_plans.log_analyze</TT>
+  (<TT CLASS="TYPE">boolean</TT>)
+</DT>
+<DD>
+<P> <TT CLASS="VARNAME">pg_store_plans.log_analyze</TT>
+  causes <TT CLASS="COMMAND">EXPLAIN ANALYZE</TT> output, rather than
+  just <TT CLASS="COMMAND">EXPLAIN</TT> output, to be included
+  in <TT CLASS="STRUCTFIELD">plan</TT>.  This parameter is off by
+  default.
+</P>
+</DD>
+<DT>
+<TT CLASS="VARNAME">pg_store_plans.log_buffers</TT>
+  (<TT CLASS="TYPE">boolean</TT>)
+</DT>
+<DD>
+<P> <TT CLASS="VARNAME">pg_store_plans.log_buffers</TT>
+  causes <TT CLASS="COMMAND">EXPLAIN (ANALYZE, BUFFERS)</TT> output,
+  rather than just <TT CLASS="COMMAND">EXPLAIN</TT> output, to be
+  included in <TT CLASS="STRUCTFIELD">plan</TT>.  This parameter is off
+  by default.
+</P>
+</DD>
+<DT>
+<TT CLASS="VARNAME">pg_store_plans.log_timing</TT>
+ (<TT CLASS="TYPE">boolean</TT>)</DT>
+<DD>
+<P> Setting <TT CLASS="VARNAME">pg_store_plans.log_timing</TT> to
+  false disables to record actual timings. The overhead of repeatedly
+  reading the system clock can slow down the query significantly on
+  some systems, so it may be useful to set this parameter to FALSE
+  when only actual row counts, and not exact execution times for each
+  execution nodes, are needed. Run time of the entire statement is
+  always measured
+  when <TT CLASS="VARNAME">pg_store_plans.log_analyze</TT> is
+  TRUE. It defaults to TRUE.
+</P>
+</DD>
+<DT>
+<TT CLASS="VARNAME">pg_store_plans.log_triggers</TT
+> (<TT CLASS="TYPE">boolean</TT
+>)</DT>
+<DD>
+<P> <TT CLASS="VARNAME">pg_store_plans.log_triggers</TT> causes
+  trigger execution statistics to be included in recoreded plans. This
+  parameter has no effect
+  unless <TT CLASS="VARNAME">pg_store_plans.log_analyze</TT> is
+  turned on.
+</P>
+</DD>
+<DT>
+<TT CLASS="VARNAME">pg_store_plans.verbose</TT>
+ (<TT CLASS="TYPE">boolean</TT>)
+</DT>
+<DD>
+<P> <TT CLASS="VARNAME">pg_store_plans.verbose</TT>
+  causes <TT CLASS="COMMAND">EXPLAIN VERBOSE</TT> output, rather than
+  just <TT CLASS="COMMAND">EXPLAIN</TT> output, to be included
+  in <TT CLASS="STRUCTFIELD">plan</TT>.  This parameter is off by
+  default.
+</P>
+</DD>
+<DT>
+<TT CLASS="VARNAME">pg_store_plans.save</TT>
+ (<TT CLASS="TYPE">boolean</TT>)
+</DT>
+<DD>
+<P> <TT CLASS="VARNAME">pg_store_plans.save</TT> specifies whether to
+  save plan statistics across server shutdowns.  If it
+  is <TT CLASS="LITERAL">off</TT> then statistics are not saved at
+  shutdown nor reloaded at server start.  The default value
+  is <TT CLASS="LITERAL">on</TT>.  This parameter can only be set in
+  the <TT CLASS="FILENAME">postgresql.conf</TT> file or on the server
+  command line.
+</P>
+</DD>
+</DL>
+</DIV>
+<P> The module requires additional shared memory proportional to
+   <TT CLASS="VARNAME">pg_store_plans.max</TT>.  Note that this memory
+   is consumed whenever the module is loaded, even if
+   <TT CLASS="VARNAME">pg_store_plans.track</TT> is set
+   to <TT CLASS="LITERAL">none</TT>.
+</P>
+<P> These parameters must be set in
+ <TT CLASS="FILENAME">postgresql.conf</TT>.  Typical usage might be:
+</P><PRE CLASS="PROGRAMLISTING"># postgresql.conf
+shared_preload_libraries = 'pg_store_plans, pg_stat_statements'
+pg_store_plans.max = 10000
+pg_store_plans.track = all</PRE>
+<P>
+</P>
+</DIV>
+<DIV CLASS="SECT2">
+<H2 CLASS="SECT2">
+<A NAME="Sample">4. Sample Output</A>
+</H2>
+<PRE CLASS="SCREEN">(postgresql.conf has following settings)
+shared_preload_libraries = 'pg_store_plans,pg_stat_statements'
+pg_store_plans.log_analyze = true
+pg_store_plans.log_timing = false
+
+bench=# SELECT pg_store_plans_reset();
+
+$ pgbench -i bench
+$ pgbench -c10 -t3000 bench
+
+bench=# \x
+bench=#  SELECT s.query, p.plan,
+        p.calls as "plan calls", s.calls as "stmt calls",
+        p.total_time / p.calls as "time/call", p.first_call, p.last_call
+        FROM pg_stat_statements s
+        JOIN pg_store_plans p ON
+        (p.queryid = pg_store_plans_hash_query(s.query) and p.calls &#60; s.calls)
+        ORDER BY query ASC, "time/call" DESC;
+-[ RECORD 1 ]----------------------------------------------------------------------------------------------------------------------------
+query      | UPDATE pgbench_branches SET bbalance = bbalance + ? WHERE bid = ?;
+plan       | Update on pgbench_branches  (cost=0.00..8.01 rows=1 width=370) (actual rows=0 loops=1)
+           |   -&#62;  Seq Scan on pgbench_branches  (cost=0.00..8.01 rows=1 width=370) (actual rows=1 loops=1)
+           |         Filter: (bid = 1)
+plan calls | 15583
+stmt calls | 30000
+time/call  | 40.096513957518
+first_call | 2014-04-25 14:29:17.163924+09
+last_call  | 2014-04-25 14:31:29.421635+09
+-[ RECORD 2 ]----------------------------------------------------------------------------------------------------------------------------
+query      | UPDATE pgbench_branches SET bbalance = bbalance + ? WHERE bid = ?;
+plan       | Update on pgbench_branches  (cost=0.12..8.14 rows=1 width=370) (actual rows=0 loops=1)
+           |   -&#62;  Index Scan using pgbench_branches_pkey on pgbench_branches  (cost=0.12..8.14 rows=1 width=370) (actual rows=1 loops=1)
+           |         Index Cond: (bid = 1)
+plan calls | 14417
+stmt calls | 30000
+time/call  | 39.1920771311645
+first_call | 2014-04-25 14:31:29.288913+09
+last_call  | 2014-04-25 14:33:31.287061+09
+-[ RECORD 3 ]----------------------------------------------------------------------------------------------------------------------------
+query      | UPDATE pgbench_tellers SET tbalance = tbalance + ? WHERE tid = ?;
+plan       | Update on pgbench_tellers  (cost=0.14..8.16 rows=1 width=358) (actual rows=0 loops=1)
+           |   -&#62;  Index Scan using pgbench_tellers_pkey on pgbench_tellers  (cost=0.14..8.16 rows=1 width=358) (actual rows=1 loops=1)
+           |         Index Cond: (tid = 7)
+plan calls | 4
+stmt calls | 30000
+time/call  | 87.0435
+first_call | 2014-04-25 14:30:37.850293+09
+last_call  | 2014-04-25 14:32:38.083977+09
+-[ RECORD 4 ]----------------------------------------------------------------------------------------------------------------------------
+query      | UPDATE pgbench_tellers SET tbalance = tbalance + ? WHERE tid = ?;
+plan       | Update on pgbench_tellers  (cost=4.14..8.16 rows=1 width=358) (actual rows=0 loops=1)
+           |   -&#62;  Bitmap Heap Scan on pgbench_tellers  (cost=4.14..8.16 rows=1 width=358) (actual rows=1 loops=1)
+           |         Recheck Cond: (tid = 10)
+           |         -&#62;  Bitmap Index Scan using pgbench_tellers_pkey  (cost=0.00..4.14 rows=1 width=0) (actual rows=1 loops=1)
+           |               Index Cond: (tid = 10)
+plan calls | 29996
+stmt calls | 30000
+time/call  | 33.6455953793834
+first_call | 2014-04-25 14:29:17.162871+09
+last_call  | 2014-04-25 14:33:31.28646+09</PRE>
+</DIV>
+</DIV>
+<HR>
+</BODY>
+</HTML>
diff --git a/doc/stylesheet.css b/doc/stylesheet.css
new file mode 100644 (file)
index 0000000..cfa0a47
--- /dev/null
@@ -0,0 +1,60 @@
+/* doc/src/sgml/stylesheet.css */
+
+/* color scheme similar to www.postgresql.org */
+
+BODY {
+       color: #000000;
+       background: #FFFFFF;
+       font-family: verdana, Arial, sans-serif;
+}
+
+A:link         { color:#0066A2; }
+A:visited      { color:#004E66; }
+A:active       { color:#0066A2; }
+A:hover                { color:#000000; }
+
+H1 {
+       font-size: 2.0em;
+       font-weight: bold;
+       margin-top: 0em;
+       margin-bottom: 0em;
+       color: #EC5800;
+}
+
+H2 {
+       font-size: 1.2em;
+       margin: 2.0em 0em 1.2em 0em;
+       font-weight: bold;
+       color: #666;
+}
+
+H3 {
+       font-size: 1.1em;
+       margin: 1.2em 0em 1.2em 0em;
+       font-weight: bold;
+       color: #666;
+}
+
+H4 {
+       font-size: 0.95em;
+       margin: 1.2em 0em 1.2em 0em;
+       font-weight: normal;
+       color: #666;
+}
+
+H5 {
+       font-size: 0.9em;
+       margin: 1.2em 0em 1.2em 0em;
+       font-weight: normal;
+}
+
+H6 {
+       font-size: 0.85em;
+       margin: 1.2em 0em 1.2em 0em;
+       font-weight: normal;
+}
+
+PRE,CODE,KBD,SAMP,TT {
+  font-family:monospace,monospace;
+  font-size:1em;
+}
\ No newline at end of file
index a22085f..98a30d1 100644 (file)
@@ -1089,20 +1089,20 @@ pg_store_plans(PG_FUNCTION_ARGS)
 
                        switch (plan_format)
                        {
-                       case PLAN_FORMAT_TEXT:
-                               pstr = pgsp_json_textize(entry->plan);
-                               break;
-                       case PLAN_FORMAT_JSON:
-                               pstr = pgsp_json_inflate(entry->plan);
-                               break;
-                       case PLAN_FORMAT_YAML:
-                               pstr = pgsp_json_yamlize(entry->plan);
-                               break;
-                       case PLAN_FORMAT_XML:
-                               pstr = pgsp_json_xmlize(entry->plan);
-                               break;
-                       default:
-                               break;
+                               case PLAN_FORMAT_TEXT:
+                                       pstr = pgsp_json_textize(entry->plan);
+                                       break;
+                               case PLAN_FORMAT_JSON:
+                                       pstr = pgsp_json_inflate(entry->plan);
+                                       break;
+                               case PLAN_FORMAT_YAML:
+                                       pstr = pgsp_json_yamlize(entry->plan);
+                                       break;
+                               case PLAN_FORMAT_XML:
+                                       pstr = pgsp_json_xmlize(entry->plan);
+                                       break;
+                               default:
+                                       break;
                        }
                        
                        estr = (char *)
index 79d3655..be54e8c 100644 (file)
@@ -73,30 +73,30 @@ SETTERDECL(strategy)
 
        switch (vals->nodetag)
        {
-       case T_Agg:
-               switch (p->tag)
-               {
-               case S_Hashed:
-                       vals->node_type = "HashAggregate"; break;
-               case S_Sorted:
-                       vals->node_type = "GroupAggregate"; break;
-               default:
+               case T_Agg:
+                       switch (p->tag)
+                       {
+                               case S_Hashed:
+                                       vals->node_type = "HashAggregate"; break;
+                               case S_Sorted:
+                                       vals->node_type = "GroupAggregate"; break;
+                               default:
+                                       break;
+                       }
                        break;
-               }
-               break;
 
-       case T_SetOp:
-               switch (p->tag)
-               {
-                       case S_Hashed:
-                               vals->node_type = "HashSetOp";
-                               break;
-                       default:
-                               break;
-               }
+               case T_SetOp:
+                       switch (p->tag)
+                       {
+                               case S_Hashed:
+                                       vals->node_type = "HashSetOp";
+                                       break;
+                               default:
+                                       break;
+                       }
 
-       default:
-               break;
+               default:
+                       break;
        }
 }
 CONVERSION_SETTER(scan_dir, conv_scandir);
@@ -254,54 +254,54 @@ print_current_node(pgspParserContext *ctx)
 
        switch (v->nodetag)
        {
-       case T_ModifyTable:
-       case T_SeqScan:
-       case T_BitmapHeapScan:
-       case T_TidScan:
-       case T_SubqueryScan:
-       case T_FunctionScan:
-       case T_ValuesScan:
-       case T_CteScan:
-       case T_WorkTableScan:
-       case T_ForeignScan:
-               if (v->nodetag == T_ModifyTable)
-                       appendStringInfoString(s, v->operation);
-               else
+               case T_ModifyTable:
+               case T_SeqScan:
+               case T_BitmapHeapScan:
+               case T_TidScan:
+               case T_SubqueryScan:
+               case T_FunctionScan:
+               case T_ValuesScan:
+               case T_CteScan:
+               case T_WorkTableScan:
+               case T_ForeignScan:
+                       if (v->nodetag == T_ModifyTable)
+                               appendStringInfoString(s, v->operation);
+                       else
+                               appendStringInfoString(s, v->node_type);
+
+                       print_obj_name(ctx);
+                       break;
+
+               case T_IndexScan:
+               case T_IndexOnlyScan:
+               case T_BitmapIndexScan:
                        appendStringInfoString(s, v->node_type);
+                       print_prop_if_exists(s, " ", v->scan_dir, 0, 0);
+                       print_prop_if_exists(s, " using ", v->index_name, 0, 0);
+                       print_obj_name(ctx);
+                       break;
 
-               print_obj_name(ctx);
-               break;
-
-       case T_IndexScan:
-       case T_IndexOnlyScan:
-       case T_BitmapIndexScan:
-               appendStringInfoString(s, v->node_type);
-               print_prop_if_exists(s, " ", v->scan_dir, 0, 0);
-               print_prop_if_exists(s, " using ", v->index_name, 0, 0);
-               print_obj_name(ctx);
-               break;
-
-       case T_NestLoop:
-       case T_MergeJoin:
-       case T_HashJoin:
-               appendStringInfoString(s, v->node_type);
-               if (v->join_type && strcmp(v->join_type, "Inner") != 0)
-               {
-                       appendStringInfoChar(s, ' ');
-                       appendStringInfoString(s, v->join_type);
-               }
-               if (v->nodetag != T_NestLoop)
-                       appendStringInfoString(s, " Join");
-               break;
-
-       case T_SetOp:
-               appendStringInfoString(s, v->node_type);
-               print_prop_if_exists(s, " ", v->setopcommand, 0, 0);
-               break;
-
-       default:
-               appendStringInfoString(s, v->node_type);
-               break;
+               case T_NestLoop:
+               case T_MergeJoin:
+               case T_HashJoin:
+                       appendStringInfoString(s, v->node_type);
+                       if (v->join_type && strcmp(v->join_type, "Inner") != 0)
+                       {
+                               appendStringInfoChar(s, ' ');
+                               appendStringInfoString(s, v->join_type);
+                       }
+                       if (v->nodetag != T_NestLoop)
+                               appendStringInfoString(s, " Join");
+                       break;
+
+               case T_SetOp:
+                       appendStringInfoString(s, v->node_type);
+                       print_prop_if_exists(s, " ", v->setopcommand, 0, 0);
+                       break;
+
+               default:
+                       appendStringInfoString(s, v->node_type);
+                       break;
        }
        
        if (!ISZERO(v->startup_cost) &&
@@ -562,14 +562,14 @@ json_text_objend(void *state)
        pgspParserContext *ctx = (pgspParserContext *)state;
        switch (ctx->processing)
        {
-       case P_Plan:
-               print_current_node(ctx);
-               break;
-       case P_Triggers:
-               print_current_trig_node(ctx);
-               break;
-       default:
-               break;
+               case P_Plan:
+                       print_current_node(ctx);
+                       break;
+               case P_Triggers:
+                       print_current_trig_node(ctx);
+                       break;
+               default:
+                       break;
        }
 
        clear_nodeval(ctx->nodevals);