QUERY PLAN
-------------------------------------------------------------------&zwsp;---------------------------------------------------------------
Index Only Scan using tenk1_four_unique1_idx on tenk1 (cost=0.29..6.90 rows=1 width=8) (actual time=0.006..0.007 rows=1.00 loops=1)
Index Cond: ((four >= 1) AND (four <= 3) AND (unique1 = 42))
Heap Fetches: 0
Index Searches: 3
Buffers: shared hit=7
Planning Time: 0.029 ms
Execution Time: 0.012 ms
</screen>
Here we see an Index-Only Scan node using
<structname>tenk1_four_unique1_idx</structname>, a multi-column index on the
<structname>tenk1</structname> table's <structfield>four</structfield> and
<structfield>unique1</structfield> columns. The scan performs 3 searches
that each read a single index leaf page:
<quote><literal>four = 1 AND unique1 = 42</literal></quote>,
<quote><literal>four = 2 AND unique1 = 42</literal></quote>, and
<quote><literal>four = 3 AND unique1 = 42</literal></quote>. This index
is generally a good target for skip scan, since, as discussed in
<xref linkend="indexes-multicolumn"/>, its leading column (the
<structfield>four</structfield> column) contains only 4 distinct values,
while its second/final column (the <structfield>unique1</structfield>
column) contains many distinct values.
</para>
<para>
Another type of extra information is the number of rows removed by a
filter condition:
<screen>
EXPLAIN ANALYZE SELECT * FROM tenk1 WHERE ten < 7;
QUERY PLAN
-------------------------------------------------------------------&zwsp;--------------------------------------
Seq Scan on tenk1 (cost=0.00..470.00 rows=7000 width=244) (actual time=0.030..1.995 rows=7000.00 loops=1)
Filter: (ten < 7)
Rows Removed by Filter: 3000
Buffers: shared hit=345
Planning Time: 0.102 ms
Execution Time: 2.145 ms
</screen>
These counts can be particularly valuable for filter conditions applied at
join nodes. The <quote>Rows Removed</quote> line only appears when at least
one scanned row, or potential join pair in the case of a join node,
is rejected by the filter condition.
</para>
<para>
A case similar to filter conditions occurs with <quote>lossy</quote>
index scans. For example, consider this search for polygons containing a
specific point:
<screen>
EXPLAIN ANALYZE SELECT * FROM polygon_tbl WHERE f1 @> polygon '(0.5,2.0)';
QUERY PLAN
-------------------------------------------------------------------&zwsp;-----------------------------------
Seq Scan on polygon_tbl (cost=0.00..1.09 rows=1 width=85) (actual time=0.023..0.023 rows=0.00 loops=1)
Filter: (f1 @> '((0.5,2))'::polygon)
Rows Removed by Filter: 7
Buffers: shared hit=1
Planning Time: 0.039 ms
Execution Time: 0.033 ms
</screen>
The planner thinks (quite correctly) that this sample table is too small
to bother with an index scan, so we have a plain sequential scan in which
all the rows got rejected by the filter condition. But if we force an
index scan to be used, we see:
<screen>
SET enable_seqscan TO off;
EXPLAIN ANALYZE SELECT * FROM polygon_tbl WHERE f1 @> polygon '(0.5,2.0)';
QUERY PLAN
-------------------------------------------------------------------&zwsp;-------------------------------------------------------
Index Scan using gpolygonind on polygon_tbl (cost=0.13..8.15 rows=1 width=85) (actual time=0.074..0.074 rows=0.00 loops=1)
Index Cond: (f1 @> '((0.5,2))'::polygon)
Rows Removed by Index Recheck: 1
Index Searches: 1
Buffers: shared hit=1
Planning Time: 0.039 ms
Execution Time: 0.098 ms
</screen>
Here we can see that the index returned one candidate row, which was
then rejected by a recheck of