1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>EXPLAIN</title><link rel="stylesheet" type="text/css" href="stylesheet.css" /><link rev="made" href="pgsql-docs@lists.postgresql.org" /><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot" /><link rel="prev" href="sql-execute.html" title="EXECUTE" /><link rel="next" href="sql-fetch.html" title="FETCH" /></head><body id="docContent" class="container-fluid col-10"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">EXPLAIN</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="sql-execute.html" title="EXECUTE">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="sql-commands.html" title="SQL Commands">Up</a></td><th width="60%" align="center">SQL Commands</th><td width="10%" align="right"><a accesskey="h" href="index.html" title="PostgreSQL 18.0 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="sql-fetch.html" title="FETCH">Next</a></td></tr></table><hr /></div><div class="refentry" id="SQL-EXPLAIN"><div class="titlepage"></div><a id="id-1.9.3.148.1" class="indexterm"></a><a id="id-1.9.3.148.2" class="indexterm"></a><a id="id-1.9.3.148.3" class="indexterm"></a><div class="refnamediv"><h2><span class="refentrytitle">EXPLAIN</span></h2><p>EXPLAIN — show the execution plan of a statement</p></div><div class="refsynopsisdiv"><h2>Synopsis</h2><pre class="synopsis">
3 EXPLAIN [ ( <em class="replaceable"><code>option</code></em> [, ...] ) ] <em class="replaceable"><code>statement</code></em>
5 <span class="phrase">where <em class="replaceable"><code>option</code></em> can be one of:</span>
7 ANALYZE [ <em class="replaceable"><code>boolean</code></em> ]
8 VERBOSE [ <em class="replaceable"><code>boolean</code></em> ]
9 COSTS [ <em class="replaceable"><code>boolean</code></em> ]
10 SETTINGS [ <em class="replaceable"><code>boolean</code></em> ]
11 GENERIC_PLAN [ <em class="replaceable"><code>boolean</code></em> ]
12 BUFFERS [ <em class="replaceable"><code>boolean</code></em> ]
13 SERIALIZE [ { NONE | TEXT | BINARY } ]
14 WAL [ <em class="replaceable"><code>boolean</code></em> ]
15 TIMING [ <em class="replaceable"><code>boolean</code></em> ]
16 SUMMARY [ <em class="replaceable"><code>boolean</code></em> ]
17 MEMORY [ <em class="replaceable"><code>boolean</code></em> ]
18 FORMAT { TEXT | XML | JSON | YAML }
19 </pre></div><div class="refsect1" id="id-1.9.3.148.7"><h2>Description</h2><p>
20 This command displays the execution plan that the
21 <span class="productname">PostgreSQL</span> planner generates for the
22 supplied statement. The execution plan shows how the table(s)
23 referenced by the statement will be scanned — by plain sequential scan,
24 index scan, etc. — and if multiple tables are referenced, what join
25 algorithms will be used to bring together the required rows from
28 The most critical part of the display is the estimated statement execution
29 cost, which is the planner's guess at how long it will take to run the
30 statement (measured in cost units that are arbitrary, but conventionally
31 mean disk page fetches). Actually two numbers
32 are shown: the start-up cost before the first row can be returned, and
33 the total cost to return all the rows. For most queries the total cost
34 is what matters, but in contexts such as a subquery in <code class="literal">EXISTS</code>, the planner
35 will choose the smallest start-up cost instead of the smallest total cost
36 (since the executor will stop after getting one row, anyway).
37 Also, if you limit the number of rows to return with a <code class="literal">LIMIT</code> clause,
38 the planner makes an appropriate interpolation between the endpoint
39 costs to estimate which plan is really the cheapest.
41 The <code class="literal">ANALYZE</code> option causes the statement to be actually
42 executed, not only planned. Then actual run time statistics are added to
43 the display, including the total elapsed time expended within each plan
44 node (in milliseconds) and the total number of rows it actually returned.
45 This is useful for seeing whether the planner's estimates
47 </p><div class="important"><h3 class="title">Important</h3><p>
48 Keep in mind that the statement is actually executed when
49 the <code class="literal">ANALYZE</code> option is used. Although
50 <code class="command">EXPLAIN</code> will discard any output that a
51 <code class="command">SELECT</code> would return, other side effects of the
52 statement will happen as usual. If you wish to use
53 <code class="command">EXPLAIN ANALYZE</code> on an
54 <code class="command">INSERT</code>, <code class="command">UPDATE</code>,
55 <code class="command">DELETE</code>, <code class="command">MERGE</code>,
56 <code class="command">CREATE TABLE AS</code>,
57 or <code class="command">EXECUTE</code> statement
58 without letting the command affect your data, use this approach:
59 </p><pre class="programlisting">
64 </p></div></div><div class="refsect1" id="id-1.9.3.148.8"><h2>Parameters</h2><div class="variablelist"><dl class="variablelist"><dt><span class="term"><code class="literal">ANALYZE</code></span></dt><dd><p>
65 Carry out the command and show actual run times and other statistics.
66 This parameter defaults to <code class="literal">FALSE</code>.
67 </p></dd><dt><span class="term"><code class="literal">VERBOSE</code></span></dt><dd><p>
68 Display additional information regarding the plan. Specifically, include
69 the output column list for each node in the plan tree, schema-qualify
70 table and function names, always label variables in expressions with
71 their range table alias, and always print the name of each trigger for
72 which statistics are displayed. The query identifier will also be
73 displayed if one has been computed, see <a class="xref" href="runtime-config-statistics.html#GUC-COMPUTE-QUERY-ID">compute_query_id</a> for more details. This parameter
74 defaults to <code class="literal">FALSE</code>.
75 </p></dd><dt><span class="term"><code class="literal">COSTS</code></span></dt><dd><p>
76 Include information on the estimated startup and total cost of each
77 plan node, as well as the estimated number of rows and the estimated
79 This parameter defaults to <code class="literal">TRUE</code>.
80 </p></dd><dt><span class="term"><code class="literal">SETTINGS</code></span></dt><dd><p>
81 Include information on configuration parameters. Specifically, include
82 options affecting query planning with value different from the built-in
83 default value. This parameter defaults to <code class="literal">FALSE</code>.
84 </p></dd><dt><span class="term"><code class="literal">GENERIC_PLAN</code></span></dt><dd><p>
85 Allow the statement to contain parameter placeholders like
86 <code class="literal">$1</code>, and generate a generic plan that does not
87 depend on the values of those parameters.
88 See <a class="link" href="sql-prepare.html" title="PREPARE"><code class="command">PREPARE</code></a>
89 for details about generic plans and the types of statement that
91 This parameter cannot be used together with <code class="literal">ANALYZE</code>.
92 It defaults to <code class="literal">FALSE</code>.
93 </p></dd><dt><span class="term"><code class="literal">BUFFERS</code></span></dt><dd><p>
94 Include information on buffer usage. Specifically, include the number of
95 shared blocks hit, read, dirtied, and written, the number of local blocks
96 hit, read, dirtied, and written, the number of temp blocks read and
97 written, and the time spent reading and writing data file blocks, local
98 blocks and temporary file blocks (in milliseconds) if
99 <a class="xref" href="runtime-config-statistics.html#GUC-TRACK-IO-TIMING">track_io_timing</a> is enabled. A
100 <span class="emphasis"><em>hit</em></span> means that a read was avoided because the block
101 was found already in cache when needed.
102 Shared blocks contain data from regular tables and indexes;
103 local blocks contain data from temporary tables and indexes;
104 while temporary blocks contain short-term working data used in sorts,
105 hashes, Materialize plan nodes, and similar cases.
106 The number of blocks <span class="emphasis"><em>dirtied</em></span> indicates the number of
107 previously unmodified blocks that were changed by this query; while the
108 number of blocks <span class="emphasis"><em>written</em></span> indicates the number of
109 previously-dirtied blocks evicted from cache by this backend during
111 The number of blocks shown for an
112 upper-level node includes those used by all its child nodes. In text
113 format, only non-zero values are printed. Buffers information is
114 automatically included when <code class="literal">ANALYZE</code> is used.
115 </p></dd><dt><span class="term"><code class="literal">SERIALIZE</code></span></dt><dd><p>
116 Include information on the cost
117 of <em class="firstterm">serializing</em> the query's output data, that
118 is converting it to text or binary format to send to the client.
119 This can be a significant part of the time required for regular
120 execution of the query, if the datatype output functions are
121 expensive or if <acronym class="acronym">TOAST</acronym>ed values must be fetched
122 from out-of-line storage. <code class="command">EXPLAIN</code>'s default
123 behavior, <code class="literal">SERIALIZE NONE</code>, does not perform these
124 conversions. If <code class="literal">SERIALIZE TEXT</code>
125 or <code class="literal">SERIALIZE BINARY</code> is specified, the appropriate
126 conversions are performed, and the time spent doing so is measured
127 (unless <code class="literal">TIMING OFF</code> is specified). If
128 the <code class="literal">BUFFERS</code> option is also specified, then any
129 buffer accesses involved in the conversions are counted too.
130 In no case, however, will <code class="command">EXPLAIN</code> actually send
131 the resulting data to the client; hence network transmission costs
132 cannot be investigated this way.
133 Serialization may only be enabled when <code class="literal">ANALYZE</code> is
134 also enabled. If <code class="literal">SERIALIZE</code> is written without an
135 argument, <code class="literal">TEXT</code> is assumed.
136 </p></dd><dt><span class="term"><code class="literal">WAL</code></span></dt><dd><p>
137 Include information on WAL record generation. Specifically, include the
138 number of records, number of full page images (fpi), the amount of WAL
139 generated in bytes and the number of times the WAL buffers became full.
140 In text format, only non-zero values are printed.
141 This parameter may only be used when <code class="literal">ANALYZE</code> is also
142 enabled. It defaults to <code class="literal">FALSE</code>.
143 </p></dd><dt><span class="term"><code class="literal">TIMING</code></span></dt><dd><p>
144 Include actual startup time and time spent in each node in the output.
145 The overhead of repeatedly reading the system clock can slow down the
146 query significantly on some systems, so it may be useful to set this
147 parameter to <code class="literal">FALSE</code> when only actual row counts, and
148 not exact times, are needed. Run time of the entire statement is
149 always measured, even when node-level timing is turned off with this
151 This parameter may only be used when <code class="literal">ANALYZE</code> is also
152 enabled. It defaults to <code class="literal">TRUE</code>.
153 </p></dd><dt><span class="term"><code class="literal">SUMMARY</code></span></dt><dd><p>
154 Include summary information (e.g., totaled timing information) after the
155 query plan. Summary information is included by default when
156 <code class="literal">ANALYZE</code> is used but otherwise is not included by
157 default, but can be enabled using this option. Planning time in
158 <code class="command">EXPLAIN EXECUTE</code> includes the time required to fetch
159 the plan from the cache and the time required for re-planning, if
161 </p></dd><dt><span class="term"><code class="literal">MEMORY</code></span></dt><dd><p>
162 Include information on memory consumption by the query planning phase.
163 Specifically, include the precise amount of storage used by planner
164 in-memory structures, as well as total memory considering allocation
166 This parameter defaults to <code class="literal">FALSE</code>.
167 </p></dd><dt><span class="term"><code class="literal">FORMAT</code></span></dt><dd><p>
168 Specify the output format, which can be TEXT, XML, JSON, or YAML.
169 Non-text output contains the same information as the text output
170 format, but is easier for programs to parse. This parameter defaults to
171 <code class="literal">TEXT</code>.
172 </p></dd><dt><span class="term"><em class="replaceable"><code>boolean</code></em></span></dt><dd><p>
173 Specifies whether the selected option should be turned on or off.
174 You can write <code class="literal">TRUE</code>, <code class="literal">ON</code>, or
175 <code class="literal">1</code> to enable the option, and <code class="literal">FALSE</code>,
176 <code class="literal">OFF</code>, or <code class="literal">0</code> to disable it. The
177 <em class="replaceable"><code>boolean</code></em> value can also
178 be omitted, in which case <code class="literal">TRUE</code> is assumed.
179 </p></dd><dt><span class="term"><em class="replaceable"><code>statement</code></em></span></dt><dd><p>
180 Any <code class="command">SELECT</code>, <code class="command">INSERT</code>, <code class="command">UPDATE</code>,
181 <code class="command">DELETE</code>, <code class="command">MERGE</code>,
182 <code class="command">VALUES</code>, <code class="command">EXECUTE</code>,
183 <code class="command">DECLARE</code>, <code class="command">CREATE TABLE AS</code>, or
184 <code class="command">CREATE MATERIALIZED VIEW AS</code> statement, whose execution
185 plan you wish to see.
186 </p></dd></dl></div></div><div class="refsect1" id="id-1.9.3.148.9"><h2>Outputs</h2><p>
187 The command's result is a textual description of the plan selected
188 for the <em class="replaceable"><code>statement</code></em>,
189 optionally annotated with execution statistics.
190 <a class="xref" href="using-explain.html" title="14.1. Using EXPLAIN">Section 14.1</a> describes the information provided.
191 </p></div><div class="refsect1" id="id-1.9.3.148.10"><h2>Notes</h2><p>
192 In order to allow the <span class="productname">PostgreSQL</span> query
193 planner to make reasonably informed decisions when optimizing
194 queries, the <a class="link" href="catalog-pg-statistic.html" title="52.51. pg_statistic"><code class="structname">pg_statistic</code></a>
195 data should be up-to-date for all tables used in the query. Normally
196 the <a class="link" href="routine-vacuuming.html#AUTOVACUUM" title="24.1.6. The Autovacuum Daemon">autovacuum daemon</a> will take care
197 of that automatically. But if a table has recently had substantial
198 changes in its contents, you might need to do a manual
199 <a class="link" href="sql-analyze.html" title="ANALYZE"><code class="command">ANALYZE</code></a> rather than wait for autovacuum to catch up
202 In order to measure the run-time cost of each node in the execution
203 plan, the current implementation of <code class="command">EXPLAIN
204 ANALYZE</code> adds profiling overhead to query execution.
205 As a result, running <code class="command">EXPLAIN ANALYZE</code>
206 on a query can sometimes take significantly longer than executing
207 the query normally. The amount of overhead depends on the nature of
208 the query, as well as the platform being used. The worst case occurs
209 for plan nodes that in themselves require very little time per
210 execution, and on machines that have relatively slow operating
211 system calls for obtaining the time of day.
212 </p></div><div class="refsect1" id="id-1.9.3.148.11"><h2>Examples</h2><p>
213 To show the plan for a simple query on a table with a single
214 <code class="type">integer</code> column and 10000 rows:
216 </p><pre class="programlisting">
217 EXPLAIN SELECT * FROM foo;
220 ---------------------------------------------------------
221 Seq Scan on foo (cost=0.00..155.00 rows=10000 width=4)
225 Here is the same query, with JSON output formatting:
226 </p><pre class="programlisting">
227 EXPLAIN (FORMAT JSON) SELECT * FROM foo;
229 --------------------------------
233 "Node Type": "Seq Scan",+
234 "Relation Name": "foo", +
236 "Startup Cost": 0.00, +
237 "Total Cost": 155.00, +
238 "Plan Rows": 10000, +
246 If there is an index and we use a query with an indexable
247 <code class="literal">WHERE</code> condition, <code class="command">EXPLAIN</code>
248 might show a different plan:
250 </p><pre class="programlisting">
251 EXPLAIN SELECT * FROM foo WHERE i = 4;
254 --------------------------------------------------------------
255 Index Scan using fi on foo (cost=0.00..5.98 rows=1 width=4)
260 Here is the same query, but in YAML format:
261 </p><pre class="programlisting">
262 EXPLAIN (FORMAT YAML) SELECT * FROM foo WHERE i='4';
264 -------------------------------
266 Node Type: "Index Scan" +
267 Scan Direction: "Forward"+
269 Relation Name: "foo" +
275 Index Cond: "(i = 4)"
279 XML format is left as an exercise for the reader.
281 Here is the same plan with cost estimates suppressed:
283 </p><pre class="programlisting">
284 EXPLAIN (COSTS FALSE) SELECT * FROM foo WHERE i = 4;
287 ----------------------------
288 Index Scan using fi on foo
293 Here is an example of a query plan for a query using an aggregate
296 </p><pre class="programlisting">
297 EXPLAIN SELECT sum(i) FROM foo WHERE i < 10;
300 ---------------------------------------------------------------------
301 Aggregate (cost=23.93..23.93 rows=1 width=4)
302 -> Index Scan using fi on foo (cost=0.00..23.92 rows=6 width=4)
303 Index Cond: (i < 10)
307 Here is an example of using <code class="command">EXPLAIN EXECUTE</code> to
308 display the execution plan for a prepared query:
310 </p><pre class="programlisting">
311 PREPARE query(int, int) AS SELECT sum(bar) FROM test
312 WHERE id > $1 AND id < $2
315 EXPLAIN ANALYZE EXECUTE query(100, 200);
318 -------------------------------------------------------------------------------------------------------------------------
319 HashAggregate (cost=10.77..10.87 rows=10 width=12) (actual time=0.043..0.044 rows=10.00 loops=1)
321 Batches: 1 Memory Usage: 24kB
322 Buffers: shared hit=4
323 -> Index Scan using test_pkey on test (cost=0.29..10.27 rows=99 width=8) (actual time=0.009..0.025 rows=99.00 loops=1)
324 Index Cond: ((id > 100) AND (id < 200))
326 Buffers: shared hit=4
327 Planning Time: 0.244 ms
328 Execution Time: 0.073 ms
332 Of course, the specific numbers shown here depend on the actual
333 contents of the tables involved. Also note that the numbers, and
334 even the selected query strategy, might vary between
335 <span class="productname">PostgreSQL</span> releases due to planner
336 improvements. In addition, the <code class="command">ANALYZE</code> command
337 uses random sampling to estimate data statistics; therefore, it is
338 possible for cost estimates to change after a fresh run of
339 <code class="command">ANALYZE</code>, even if the actual distribution of data
340 in the table has not changed.
342 Notice that the previous example showed a <span class="quote">“<span class="quote">custom</span>”</span> plan
343 for the specific parameter values given in <code class="command">EXECUTE</code>.
344 We might also wish to see the generic plan for a parameterized
345 query, which can be done with <code class="literal">GENERIC_PLAN</code>:
347 </p><pre class="programlisting">
348 EXPLAIN (GENERIC_PLAN)
349 SELECT sum(bar) FROM test
350 WHERE id > $1 AND id < $2
354 -------------------------------------------------------------------------------
355 HashAggregate (cost=26.79..26.89 rows=10 width=12)
357 -> Index Scan using test_pkey on test (cost=0.29..24.29 rows=500 width=8)
358 Index Cond: ((id > $1) AND (id < $2))
362 In this case the parser correctly inferred that <code class="literal">$1</code>
363 and <code class="literal">$2</code> should have the same data type
364 as <code class="literal">id</code>, so the lack of parameter type information
365 from <code class="command">PREPARE</code> was not a problem. In other cases
366 it might be necessary to explicitly specify types for the parameter
367 symbols, which can be done by casting them, for example:
369 </p><pre class="programlisting">
370 EXPLAIN (GENERIC_PLAN)
371 SELECT sum(bar) FROM test
372 WHERE id > $1::integer AND id < $2::integer
375 </p></div><div class="refsect1" id="id-1.9.3.148.12"><h2>Compatibility</h2><p>
376 There is no <code class="command">EXPLAIN</code> statement defined in the SQL standard.
378 The following syntax was used before <span class="productname">PostgreSQL</span>
379 version 9.0 and is still supported:
380 </p><pre class="synopsis">
381 EXPLAIN [ ANALYZE ] [ VERBOSE ] <em class="replaceable"><code>statement</code></em>
383 Note that in this syntax, the options must be specified in exactly the order
385 </p></div><div class="refsect1" id="id-1.9.3.148.13"><h2>See Also</h2><span class="simplelist"><a class="xref" href="sql-analyze.html" title="ANALYZE"><span class="refentrytitle">ANALYZE</span></a></span></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="sql-execute.html" title="EXECUTE">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="sql-commands.html" title="SQL Commands">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="sql-fetch.html" title="FETCH">Next</a></td></tr><tr><td width="40%" align="left" valign="top">EXECUTE </td><td width="20%" align="center"><a accesskey="h" href="index.html" title="PostgreSQL 18.0 Documentation">Home</a></td><td width="40%" align="right" valign="top"> FETCH</td></tr></table></div></body></html>