@ -60,11 +60,12 @@ EXPLAIN [ ANALYZE ] [ VERBOSE ] <replaceable class="parameter">statement</replac
<para>
<para>
The most critical part of the display is the estimated statement execution
The most critical part of the display is the estimated statement execution
cost, which is the planner's guess at how long it will take to run the
cost, which is the planner's guess at how long it will take to run the
statement (measured in units of disk page fetches). Actually two numbers
statement (measured in cost units that are arbitrary, but conventionally
are shown: the start-up time before the first row can be returned, and
mean disk page fetches). Actually two numbers
the total time to return all the rows. For most queries the total time
are shown: the start-up cost before the first row can be returned, and
the total cost to return all the rows. For most queries the total cost
is what matters, but in contexts such as a subquery in <literal>EXISTS</literal>, the planner
is what matters, but in contexts such as a subquery in <literal>EXISTS</literal>, the planner
will choose the smallest start-up time instead of the smallest total time
will choose the smallest start-up cos t instead of the smallest total cos t
(since the executor will stop after getting one row, anyway).
(since the executor will stop after getting one row, anyway).
Also, if you limit the number of rows to return with a <literal>LIMIT</literal> clause,
Also, if you limit the number of rows to return with a <literal>LIMIT</literal> clause,
the planner makes an appropriate interpolation between the endpoint
the planner makes an appropriate interpolation between the endpoint
@ -72,10 +73,11 @@ EXPLAIN [ ANALYZE ] [ VERBOSE ] <replaceable class="parameter">statement</replac
</para>
</para>
<para>
<para>
The <literal>ANALYZE</literal> option causes the statement to be actually executed, not only
The <literal>ANALYZE</literal> option causes the statement to be actually
planned. The total elapsed time expended within each plan node (in
executed, not only planned. Then actual runtime statistics are added to
milliseconds) and total number of rows it actually returned are added to
the display, including the total elapsed time expended within each plan
the display. This is useful for seeing whether the planner's estimates
node (in milliseconds) and the total number of rows it actually returned.
This is useful for seeing whether the planner's estimates
are close to reality.
are close to reality.
</para>
</para>
@ -116,8 +118,8 @@ ROLLBACK;
<term><literal>ANALYZE</literal></term>
<term><literal>ANALYZE</literal></term>
<listitem>
<listitem>
<para>
<para>
Carry out the command and show the actual run times. This
Carry out the command and show actual run times and other statistics.
parameter defaults to <literal>FALSE</literal>.
This parameter defaults to <literal>FALSE</literal>.
</para>
</para>
</listitem>
</listitem>
</varlistentry>
</varlistentry>
@ -154,12 +156,16 @@ ROLLBACK;
Include information on buffer usage. Specifically, include the number of
Include information on buffer usage. Specifically, include the number of
shared blocks hits, reads, and writes, the number of local blocks hits,
shared blocks hits, reads, and writes, the number of local blocks hits,
reads, and writes, and the number of temp blocks reads and writes.
reads, and writes, and the number of temp blocks reads and writes.
Shared blocks, local blocks, and temp blocks contain tables and indexes,
A <quote>hit</> means that a read was avoided because the block was
temporary tables and temporary indexes, and disk blocks used in sort and
found already in cache when needed.
materialized plans, respectively. The number of blocks shown for an
Shared blocks contain data from regular tables and indexes;
local blocks contain data from temporary tables and indexes;
while temp blocks contain short-term working data used in sorts, hashes,
Materialize plan nodes, and similar cases.
The number of blocks shown for an
upper-level node includes those used by all its child nodes. In text
upper-level node includes those used by all its child nodes. In text
format, only non-zero values are printed. This parameter may only be
format, only non-zero values are printed. This parameter may only be
used with <literal>ANALYZE</literal> parameter. It defaults to
used when <literal>ANALYZE</literal> is also enabled . It defaults to
<literal>FALSE</literal>.
<literal>FALSE</literal>.
</para>
</para>
</listitem>
</listitem>
@ -206,35 +212,43 @@ ROLLBACK;
</refsect1>
</refsect1>
<refsect1>
<refsect1>
<title>Note s</title>
<title>Output s</title>
<para>
<para>
There is only sparse documentation on the optimizer's use of cost
The command's result is a textual description of the plan selected
information in <productname>PostgreSQL</productname>. Refer to
for the <replaceable class="parameter">statement</replaceable>,
<xref linkend="using-explain"> for more information.
optionally annotated with execution statistics.
</para>
<xref linkend="using-explain"> describes the information provided.
</para>
</refsect1>
<refsect1>
<title>Notes</title>
<para>
<para>
In order to allow the <productname>PostgreSQL</productname> query
In order to allow the <productname>PostgreSQL</productname> query
planner to make reasonably informed decisions when optimizing
planner to make reasonably informed decisions when optimizing
queries, the <xref linkend="sql-analyze">
queries, the <link
statement should be run to record statistics about the distribution
linkend="catalog-pg-statistic"><structname>pg_statistic</structname></link>
of data within the table. If you have not done this (or if the
data should be up-to-date for all tables used in the query. Normally
statistical distribution of the data in the table has changed
the <link linkend="autovacuum">autovacuum daemon</link> will take care
significantly since the last time <command>ANALYZE</command> was
of that automatically. But if a table has recently had substantial
run), the estimated costs are unlikely to conform to the re al
changes in its contents, you might need to do a manu al
properties of the query, and consequently an inferior query plan
<xref linkend="sql-analyze"> rather than wait for autovacuum to catch up
might be chosen .
with the changes .
</para>
</para>
<para>
<para>
In order to measure the run-time cost of each node in the execution
In order to measure the run-time cost of each node in the execution
plan, the current implementation of <command>EXPLAIN
plan, the current implementation of <command>EXPLAIN
ANALYZE</command> can add con siderable profiling overhead to query
ANALYZE</command> adds profiling overhead to query execution.
execution. As a result, running <command>EXPLAIN ANALYZE</command>
As a result, running <command>EXPLAIN ANALYZE</command>
on a query can sometimes take significantly longer than executing
on a query can sometimes take significantly longer than executing
the query normally. The amount of overhead depends on the nature of
the query normally. The amount of overhead depends on the nature of
the query.
the query, as well as the platform being used. The worst case occurs
for plan nodes that in themselves require very little time per
execution, and on machines that have relatively slow operating
system calls for obtaining the time of day.
</para>
</para>
</refsect1>
</refsect1>
@ -256,10 +270,10 @@ EXPLAIN SELECT * FROM foo;
</para>
</para>
<para>
<para>
Here is the same query, with JSON formatting:
Here is the same query, with JSON output formatting:
<programlisting>
<programlisting>
EXPLAIN (FORMAT JSON) SELECT * FROM foo;
EXPLAIN (FORMAT JSON) SELECT * FROM foo;
QUERY PLAN
QUERY PLAN
--------------------------------
--------------------------------
[ +
[ +
{ +
{ +
@ -295,10 +309,10 @@ EXPLAIN SELECT * FROM foo WHERE i = 4;
</para>
</para>
<para>
<para>
Here is the same query, but in YAML outpu t:
Here is the same query, but in YAML forma t:
<programlisting>
<programlisting>
EXPLAIN (FORMAT YAML) SELECT * FROM foo WHERE i='4';
EXPLAIN (FORMAT YAML) SELECT * FROM foo WHERE i='4';
QUERY PLAN
QUERY PLAN
-------------------------------
-------------------------------
- Plan: +
- Plan: +
Node Type: "Index Scan" +
Node Type: "Index Scan" +
@ -314,10 +328,10 @@ EXPLAIN (FORMAT YAML) SELECT * FROM foo WHERE i='4';
(1 row)
(1 row)
</programlisting>
</programlisting>
XML output is left as an exercise to the reader.
XML format is left as an exercise for the reader.
</para>
</para>
<para>
<para>
Here is the same plan with costs suppressed:
Here is the same plan with cost estimate s suppressed:
<programlisting>
<programlisting>
EXPLAIN (COSTS FALSE) SELECT * FROM foo WHERE i = 4;
EXPLAIN (COSTS FALSE) SELECT * FROM foo WHERE i = 4;
@ -357,7 +371,7 @@ PREPARE query(int, int) AS SELECT sum(bar) FROM test
EXPLAIN ANALYZE EXECUTE query(100, 200);
EXPLAIN ANALYZE EXECUTE query(100, 200);
QUERY PLAN
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
HashAggregate (cost=39.53..39.53 rows=1 width=8) (actual time=0.661..0.672 rows=7 loops=1)
HashAggregate (cost=39.53..39.53 rows=1 width=8) (actual time=0.661..0.672 rows=7 loops=1)
-> 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 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)