11<!--
2- $Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.18 2002/03/22 19:20:17 petere Exp $
2+ $Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.19 2002/03/24 04:31:05 tgl Exp $
33-->
44
55 <chapter id="performance-tips">
@@ -47,8 +47,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.18 2002/03/22 19:20:17 pet
4747
4848 <listitem>
4949 <para>
50- Estimated number of rows output by this plan node (again,without
51- regard for any LIMIT ).
50+ Estimated number of rows output by this plan node (again,only if
51+ executed to completion ).
5252 </para>
5353 </listitem>
5454
@@ -92,13 +92,13 @@ $Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.18 2002/03/22 19:20:17 pet
9292
9393 <para>
9494 Here are some examples (using the regress test database after a
95- vacuum analyze, and 7.2 development sources):
95+ vacuum analyze, and 7.3 development sources):
9696
9797 <programlisting>
9898regression=# EXPLAIN SELECT * FROM tenk1;
99- INFO: QUERY PLAN:
100-
101- Seq Scan on tenk1 (cost=0.00..333.00 rows=10000 width=148)
99+ QUERY PLAN
100+ -------------------------------------------------------------
101+ Seq Scan on tenk1 (cost=0.00..333.00 rows=10000 width=148)
102102 </programlisting>
103103 </para>
104104
@@ -120,9 +120,10 @@ SELECT * FROM pg_class WHERE relname = 'tenk1';
120120
121121 <programlisting>
122122regression=# EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 1000;
123- INFO: QUERY PLAN:
124-
125- Seq Scan on tenk1 (cost=0.00..358.00 rows=1007 width=148)
123+ QUERY PLAN
124+ ------------------------------------------------------------
125+ Seq Scan on tenk1 (cost=0.00..358.00 rows=1033 width=148)
126+ Filter: (unique1 < 1000)
126127 </programlisting>
127128
128129 The estimate of output rows has gone down because of the WHERE clause.
@@ -145,9 +146,10 @@ Seq Scan on tenk1 (cost=0.00..358.00 rows=1007 width=148)
145146
146147 <programlisting>
147148regression=# EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 50;
148- INFO: QUERY PLAN:
149-
150- Index Scan using tenk1_unique1 on tenk1 (cost=0.00..181.09 rows=49 width=148)
149+ QUERY PLAN
150+ -------------------------------------------------------------------------------
151+ Index Scan using tenk1_unique1 on tenk1 (cost=0.00..179.33 rows=49 width=148)
152+ Index Filter: (unique1 < 50)
151153 </programlisting>
152154
153155 and you will see that if we make the WHERE condition selective
@@ -164,13 +166,20 @@ Index Scan using tenk1_unique1 on tenk1 (cost=0.00..181.09 rows=49 width=148)
164166 <programlisting>
165167regression=# EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 50 AND
166168regression-# stringu1 = 'xxx';
167- INFO: QUERY PLAN:
168-
169- Index Scan using tenk1_unique1 on tenk1 (cost=0.00..181.22 rows=1 width=148)
169+ QUERY PLAN
170+ -------------------------------------------------------------------------------
171+ Index Scan using tenk1_unique1 on tenk1 (cost=0.00..179.45 rows=1 width=148)
172+ Index Filter: (unique1 < 50)
173+ Filter: (stringu1 = 'xxx'::name)
170174 </programlisting>
171175
172- The added clause <literal>stringu1 = 'xxx'</literal> reduces the output-rows estimate,
173- but not the cost because we still have to visit the same set of tuples.
176+ The added clause <literal>stringu1 = 'xxx'</literal> reduces the
177+ output-rows estimate, but not the cost because we still have to visit the
178+ same set of tuples. Notice that the <literal>stringu1</> clause
179+ cannot be applied as an index condition (since this index is only on
180+ the <literal>unique1</> column). Instead it is applied as a filter on
181+ the rows retrieved by the index. Thus the cost has actually gone up
182+ a little bit to reflect this extra checking.
174183 </para>
175184
176185 <para>
@@ -179,13 +188,15 @@ Index Scan using tenk1_unique1 on tenk1 (cost=0.00..181.22 rows=1 width=148)
179188 <programlisting>
180189regression=# EXPLAIN SELECT * FROM tenk1 t1, tenk2 t2 WHERE t1.unique1 < 50
181190regression-# AND t1.unique2 = t2.unique2;
182- INFO: QUERY PLAN:
183-
184- Nested Loop (cost=0.00..330.41 rows=49 width=296)
185- -> Index Scan using tenk1_unique1 on tenk1 t1
186- (cost=0.00..181.09 rows=49 width=148)
187- -> Index Scan using tenk2_unique2 on tenk2 t2
188- (cost=0.00..3.01 rows=1 width=148)
191+ QUERY PLAN
192+ ----------------------------------------------------------------------------
193+ Nested Loop (cost=0.00..327.02 rows=49 width=296)
194+ -> Index Scan using tenk1_unique1 on tenk1 t1
195+ (cost=0.00..179.33 rows=49 width=148)
196+ Index Filter: (unique1 < 50)
197+ -> Index Scan using tenk2_unique2 on tenk2 t2
198+ (cost=0.00..3.01 rows=1 width=148)
199+ Index Filter: ("outer".unique2 = t2.unique2)
189200 </programlisting>
190201 </para>
191202
@@ -227,14 +238,15 @@ regression=# set enable_nestloop = off;
227238SET VARIABLE
228239regression=# EXPLAIN SELECT * FROM tenk1 t1, tenk2 t2 WHERE t1.unique1 < 50
229240regression-# AND t1.unique2 = t2.unique2;
230- INFO: QUERY PLAN:
231-
232- Hash Join (cost=181.22..564.83 rows=49 width=296)
233- -> Seq Scan on tenk2 t2
234- (cost=0.00..333.00 rows=10000 width=148)
235- -> Hash (cost=181.09..181.09 rows=49 width=148)
236- -> Index Scan using tenk1_unique1 on tenk1 t1
237- (cost=0.00..181.09 rows=49 width=148)
241+ QUERY PLAN
242+ --------------------------------------------------------------------------
243+ Hash Join (cost=179.45..563.06 rows=49 width=296)
244+ Hash Cond: ("outer".unique2 = "inner".unique2)
245+ -> Seq Scan on tenk2 t2 (cost=0.00..333.00 rows=10000 width=148)
246+ -> Hash (cost=179.33..179.33 rows=49 width=148)
247+ -> Index Scan using tenk1_unique1 on tenk1 t1
248+ (cost=0.00..179.33 rows=49 width=148)
249+ Index Filter: (unique1 < 50)
238250 </programlisting>
239251
240252 This plan proposes to extract the 50 interesting rows of <classname>tenk1</classname>
@@ -245,7 +257,7 @@ Hash Join (cost=181.22..564.83 rows=49 width=296)
245257 cost for the hash join, since we won't get any tuples out until we can
246258 start reading <classname>tenk2</classname>. The total time estimate for the join also
247259 includes a hefty charge for CPU time to probe the hash table
248- 10000 times. Note, however, that we are NOT charging 10000 times181.09 ;
260+ 10000 times. Note, however, that we are NOT charging 10000 times179.33 ;
249261 the hash table setup is only done once in this plan type.
250262 </para>
251263
@@ -260,14 +272,19 @@ Hash Join (cost=181.22..564.83 rows=49 width=296)
260272regression=# EXPLAIN ANALYZE
261273regression-# SELECT * FROM tenk1 t1, tenk2 t2
262274regression-# WHERE t1.unique1 < 50 AND t1.unique2 = t2.unique2;
263- INFO: QUERY PLAN:
264-
265- Nested Loop (cost=0.00..330.41 rows=49 width=296) (actual time=1.31..28.90 rows=50 loops=1)
266- -> Index Scan using tenk1_unique1 on tenk1 t1
267- (cost=0.00..181.09 rows=49 width=148) (actual time=0.69..8.84 rows=50 loops=1)
268- -> Index Scan using tenk2_unique2 on tenk2 t2
269- (cost=0.00..3.01 rows=1 width=148) (actual time=0.28..0.31 rows=1 loops=50)
270- Total runtime: 30.67 msec
275+ QUERY PLAN
276+ -------------------------------------------------------------------------------
277+ Nested Loop (cost=0.00..327.02 rows=49 width=296)
278+ (actual time=1.18..29.82 rows=50 loops=1)
279+ -> Index Scan using tenk1_unique1 on tenk1 t1
280+ (cost=0.00..179.33 rows=49 width=148)
281+ (actual time=0.63..8.91 rows=50 loops=1)
282+ Index Filter: (unique1 < 50)
283+ -> Index Scan using tenk2_unique2 on tenk2 t2
284+ (cost=0.00..3.01 rows=1 width=148)
285+ (actual time=0.29..0.32 rows=1 loops=50)
286+ Index Filter: ("outer".unique2 = t2.unique2)
287+ Total runtime: 31.60 msec
271288</screen>
272289
273290 Note that the <quote>actual time</quote> values are in milliseconds of
@@ -296,7 +313,7 @@ Total runtime: 30.67 msec
296313 little larger than the total time reported for the top-level plan node.
297314 For INSERT, UPDATE, and DELETE queries, the total run time may be
298315 considerably larger, because it includes the time spent processing the
299- output tuples. In these queries, the time for the top plan node
316+ result tuples. In these queries, the time for the top plan node
300317 essentially is the time spent computing the new tuples and/or locating
301318 the old ones, but it doesn't include the time spent making the changes.
302319 </para>