{
  "status": "shipping",
  "advantages": [],
  "limitations": [],
  "supersedes": [],
  "supersededBy": [],
  "firstSeen": null,
  "lastSeen": null,
  "updated": "2026-10-22",
  "slug": "postgresql-index-only-scan",
  "term": "Index-only scan (PostgreSQL)",
  "aliases": [
    "PostgreSQL index-only scan"
  ],
  "definition": "A PostgreSQL index-only scan retrieves values from index entries and consults the heap when visibility cannot be established from the visibility map.",
  "note": "The index must support returning the needed values, and the query must be answerable from that index. A covering index can carry extra payload columns through INCLUDE, but that duplicates data and can increase index size. [ios]\n\nThe plan name does not promise zero heap visits. For a candidate index tuple, a set all-visible map bit permits skipping the heap visibility check. A clear bit requires that check; returned values still come from the index. [ios] [scan-code]\n\nIn REL_16_15, Heap Fetches counts attempts to fetch a heap tuple for visibility, including attempts that find no visible tuple. It does not count unique pages or physical disk reads, and it is not a checksum-verification counter. [scan-code]",
  "related": [
    "postgresql-visibility-map",
    "postgresql-toast",
    "detoasting",
    "b-tree",
    "b-link-tree"
  ],
  "citations": [
    {
      "id": "ios",
      "title": "PostgreSQL 16: Index-Only Scans and Covering Indexes",
      "url": "https://www.postgresql.org/docs/16/indexes-index-only-scans.html",
      "accessed": "2026-10-21"
    },
    {
      "id": "vm",
      "title": "PostgreSQL 16: Visibility Map",
      "url": "https://www.postgresql.org/docs/16/storage-vm.html",
      "accessed": "2026-10-21"
    },
    {
      "id": "scan-code",
      "title": "PostgreSQL REL_16_15: IndexOnlyNext, visibility checks and heap-fetch instrumentation",
      "url": "https://github.com/postgres/postgres/blob/7d3e000c5961a544302072058a1184e9a588837b/src/backend/executor/nodeIndexonlyscan.c",
      "accessed": "2026-10-21"
    }
  ],
  "provenance": [
    "The counter interpretation is scoped to PostgreSQL REL_16_15. The linked Observatory demonstration uses synthetic clean rows, not injected corruption or a disk-I/O benchmark."
  ]
}
