> **Index Only Scan**
> <table>
> <tr>
> <td width="25%"><img src="assets/ex_indexonlyscan.png"></td>
> <td>An advanced optimization that retrieves all required columns directly from the index. By avoiding the 'Heap' (table files) entirely, it significantly reduces I/O. This requires the index to contain all requested columns and the Visibility Map to confirm the pages are 'all-visible'.</td>
> </tr>
> </table>
>
> ```sql
> -- Reading a visible range entirely from the primary-key index
> SET enable_seqscan = off;
>
> EXPLAIN (ANALYZE, COSTS, BUFFERS, VERBOSE)
> SELECT id FROM animals WHERE id <= 500000;
> ```
>
> 
>
> <!-- literal-explain-plan
> Captured EXPLAIN provenance for the adjacent reader-facing visual plan.
> Canonical capture metadata lives in scratch/actual_operation_plans.json.
>
> Index Only Scan using animals_pkey on public.animals (cost=0.43..13838.40 rows=486055 width=4) (actual time=0.090..34.963 rows=500000.00 loops=1)
> Output: id
> Index Cond: (animals.id <= 500000)
> Heap Fetches: 0
> Index Searches: 1
> Buffers: shared read=1370
> I/O Timings: shared read=8.128
> Query Identifier: 3962809790011388872
> Planning:
> Buffers: shared hit=74 read=4
> I/O Timings: shared read=0.064
> Planning Time: 0.221 ms
> Execution Time: 47.541 ms
> -->
>
>
> <!--
> Raw-capture provenance — separate run.
> SQL, setup, dataset, settings, and scope: artifacts/chapter4_capture_matrix.json.
> Target: PostgreSQL 18.x companion fixture. Cache state: uncontrolled.
> Boundary: pg_wait_tracer backend execution root; client states are included when the chart shows them.
> Fidelity: exact pg_wait_tracer export. Not the adjacent EXPLAIN run; compare state shape, not durations.
> -->
>
> 
>
> <table>
> <tr>
> <td rowspan="2" width="25%"><img src="assets/ex_index_only_scan.svg"></td>
> <td><b>Performance</b></td><td>Extremely efficient as it avoids random heap I/O.</td>
> </tr>
> <tr><td><b>Cost</b></td><td><code>index cost + cpu_index_tuple_cost * number of index entries</code></td></tr>
> </table>