← Concepts

阅读中文版本

Covering Index Design

A covering index includes every column the query reads, so the engine satisfies the query from the index alone without a heap fetch, turning a table scan into an index-only scan.

database

Definition

A covering index is one whose key columns and included columns together contain every column the query references, so that the query can be satisfied entirely from the index without fetching the base row, eliminating the random I/O of the heap lookup and often an order of magnitude faster.

Context and scope

Applied in read-heavy OLTP and analytical lookups where the heap fetch dominates the cost and the query column set is stable enough to index.

Common misconceptions

  • A covering index is always better — it is better for the queries it covers; it adds write amplification and storage, so it is a trade-off, not a default
  • INCLUDE columns are just extra key columns — INCLUDE columns are stored at the leaf without participating in the index order, so they do not help seeks but do help covering

Anti-patterns

  • Adding every column the table has to a covering index, producing an index as large as the table that helps one query and hurts every write
  • Covering a query whose column list changes every release, so the index is rebuilt as often as the query changes

Related concepts

Authoritative source

https://use-the-index-luke.com/sql/clauses/index-only-scan

What it is

A covering index is one whose key columns and included columns together contain every column the query references, so that the query can be satisfied entirely from the index without fetching the base row, eliminating the random I/O of the heap lookup and often an order of magnitude faster. Applied in read-heavy OLTP and analytical lookups where the heap fetch dominates the cost and the query column set is stable enough to index. The data model and the access patterns are co-designed: a schema that is correct in the relational sense can be catastrophic for the queries the workload actually issues.

How it works

Indexing decisions follow the query shapes, not the column importance: a covering index turns a table scan into an index-only scan, but every index adds write amplification and storage cost. Partitioning aligns with the access dimension so a query touches one partition, not all. Transaction scope is minimized to hold locks briefly; long transactions are the root of contention and deadlock.

When to apply and pitfalls

Apply when data volume or query latency has a concrete business cost. The common pitfall is indexing for the current workload and ignoring the access patterns that growth will introduce — the index that helps today can serialize writes tomorrow. Another is treating the database as a black box, missing that the optimizer’s plan choice depends on statistics that drift as data changes.