DEV Community

Namrata Khorjuwekar
Namrata Khorjuwekar

Posted on

SQL Server Heaps: Understanding Tables Without Clustered Indexes

Database Deep Dive Series – Part 1

Welcome to the Database Deep Dive Series, where I explore database concepts through practical examples, SQL scripts, interview questions, and real-world scenarios.

In this first article, we'll look at one of the most misunderstood SQL Server storage structures: Heaps.


What is a Heap?

A Heap is a SQL Server table that does not have a clustered index.

Unlike a clustered table, rows in a heap are not stored according to a clustering key. SQL Server simply places new rows wherever space is available.

A heap is represented internally with:

index_id = 0
Enter fullscreen mode Exit fullscreen mode

Having no clustered index doesn't mean the table cannot have indexes. A heap can still contain one or more nonclustered indexes.


How Does SQL Server Store Data in a Heap?

When a row is inserted into a heap, SQL Server writes it to an available data page rather than maintaining any logical order.

Because there is no clustered index, SQL Server identifies rows using a Row Identifier (RID).

A RID contains:

  • File ID
  • Page ID
  • Slot ID

Think of the RID as the physical address of a row inside the database.


Heap vs. Clustered Table

Heap Clustered Table
No clustered index Has a clustered index
Rows stored wherever space is available Rows stored according to the clustered key
Uses RID to locate rows Uses clustered key
Good for bulk inserts Better for frequent queries

When Should You Use a Heap?

A heap isn't better or worse than a clustered tableβ€”it depends on the workload.

Typical scenarios where a heap works well include:

  • ETL staging tables
  • Bulk data imports
  • Temporary processing tables
  • Tables that are frequently truncated and reloaded

In these situations, avoiding clustered index maintenance can improve insert performance.


When Should You Avoid a Heap?

Heaps aren't ideal for every workload.

Consider a clustered index if your table:

  • Is frequently queried
  • Performs range searches
  • Requires ordered results
  • Experiences frequent updates
  • Supports an OLTP application

Choosing the right storage structure should always depend on how the table is used.


Understanding Forwarded Records

One concept every SQL Server DBA should know is Forwarded Records.

Imagine a row grows after an UPDATE and no longer fits on its original page.

SQL Server may:

  1. Move the row to another page.
  2. Leave a forwarding pointer behind.
  3. Follow that pointer whenever the row is accessed.

Over time, too many forwarded records can increase I/O and reduce scan performance.

If a heap experiences frequent updates, it's worth monitoring forwarded records as part of regular database maintenance.


Identifying Heap Tables

The following query lists heap tables in the current database.

SELECT
    s.name AS SchemaName,
    t.name AS TableName
FROM sys.tables t
JOIN sys.schemas s
    ON t.schema_id = s.schema_id
WHERE OBJECTPROPERTY(t.object_id,'TableHasClustIndex') = 0;
Enter fullscreen mode Exit fullscreen mode

List All Heaps with Row Counts

SELECT
    OBJECT_SCHEMA_NAME(i.object_id) AS SchemaName,
    OBJECT_NAME(i.object_id) AS TableName,
    p.rows
FROM sys.indexes i
JOIN sys.partitions p
ON i.object_id = p.object_id
AND i.index_id = p.index_id
WHERE i.index_id = 0;
Enter fullscreen mode Exit fullscreen mode

Find Forwarded Records

SELECT
    OBJECT_NAME(object_id) AS TableName,
    forwarded_record_count
FROM sys.dm_db_index_physical_stats
(
    DB_ID(),
    NULL,
    NULL,
    NULL,
    'DETAILED'
)
WHERE index_id = 0;
Enter fullscreen mode Exit fullscreen mode

Real-World Scenario

Suppose you have a staging table that loads 150 million rows every night.

The data is transformed, exported, and the table is truncated before the next load.

Would you create a clustered index?

Probably not.

Since the table is primarily used for fast inserts and temporary processing, a heap may be the better choice. If the table later supports reporting or frequent lookups, adding a clustered index may improve overall performance.


SQL Server Heap Interview Prep

What is a Heap?

A heap is a table without a clustered index. SQL Server stores rows without maintaining a clustered key order and identifies them using Row Identifiers (RIDs).

What is a RID?

RID stands for Row Identifier.

It consists of:

  • File ID
  • Page ID
  • Slot ID

What are Forwarded Records?

Forwarded records occur when an updated row no longer fits on its original page. SQL Server moves the row and leaves a forwarding pointer behind.

When would you choose a Heap over a Clustered Index?

Heaps are useful for staging tables, ETL processes, bulk imports, and temporary tables where insert performance is more important than ordered data retrieval.


Best Practices

  • Use heaps for staging and ETL workloads.
  • Monitor forwarded records regularly.
  • Review heap performance if update activity increases.
  • Add appropriate nonclustered indexes when required.
  • Choose storage structures based on workload, not habit.

Common Mistakes

  • Assuming heaps are always faster.
  • Using heaps for heavily queried OLTP tables.
  • Ignoring forwarded records.
  • Creating unnecessary nonclustered indexes without considering maintenance costs.

Key Takeaways

  • A heap is simply a table without a clustered index.
  • Rows are located using Row Identifiers (RIDs).
  • Heaps work well for bulk loading and temporary processing.
  • Forwarded records can reduce performance over time.
  • Always choose the storage structure that best fits your workload.

Discussion

Have you used heaps in production?

If so, what type of workload benefited the most? Have you ever encountered performance issues caused by forwarded records?

I'd love to hear about your experience in the comments.


Database Deep Dive Series

πŸ“˜ Part 1 – SQL Server Heaps βœ…

➑️ Next Article: Clustered Indexes – How SQL Server Organizes Data

Top comments (0)