<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Namrata Khorjuwekar</title>
    <description>The latest articles on DEV Community by Namrata Khorjuwekar (@namrata_khorjuwekar_).</description>
    <link>https://dev.to/namrata_khorjuwekar_</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2307269%2F8370c38c-f5aa-41d1-8da6-a7e26df83aad.png</url>
      <title>DEV Community: Namrata Khorjuwekar</title>
      <link>https://dev.to/namrata_khorjuwekar_</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/namrata_khorjuwekar_"/>
    <language>en</language>
    <item>
      <title>SQL Server Heaps: Understanding Tables Without Clustered Indexes</title>
      <dc:creator>Namrata Khorjuwekar</dc:creator>
      <pubDate>Tue, 07 Jul 2026 04:00:23 +0000</pubDate>
      <link>https://dev.to/namrata_khorjuwekar_/sql-server-heaps-nfl</link>
      <guid>https://dev.to/namrata_khorjuwekar_/sql-server-heaps-nfl</guid>
      <description>&lt;h1&gt;
  
  
  Database Deep Dive Series – Part 1
&lt;/h1&gt;

&lt;p&gt;Welcome to the &lt;strong&gt;Database Deep Dive Series&lt;/strong&gt;, where I explore database concepts through practical examples, SQL scripts, interview questions, and real-world scenarios.&lt;/p&gt;

&lt;p&gt;In this first article, we'll look at one of the most misunderstood SQL Server storage structures: &lt;strong&gt;Heaps&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is a Heap?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;Heap&lt;/strong&gt; is a SQL Server table that &lt;strong&gt;does not have a clustered index&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;A heap is represented internally with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;index_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Having no clustered index doesn't mean the table cannot have indexes. A heap can still contain one or more nonclustered indexes.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Does SQL Server Store Data in a Heap?
&lt;/h2&gt;

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

&lt;p&gt;Because there is no clustered index, SQL Server identifies rows using a &lt;strong&gt;Row Identifier (RID)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A RID contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;File ID&lt;/li&gt;
&lt;li&gt;Page ID&lt;/li&gt;
&lt;li&gt;Slot ID&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of the RID as the physical address of a row inside the database.&lt;/p&gt;




&lt;h2&gt;
  
  
  Heap vs. Clustered Table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Heap&lt;/th&gt;
&lt;th&gt;Clustered Table&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;No clustered index&lt;/td&gt;
&lt;td&gt;Has a clustered index&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rows stored wherever space is available&lt;/td&gt;
&lt;td&gt;Rows stored according to the clustered key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uses RID to locate rows&lt;/td&gt;
&lt;td&gt;Uses clustered key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Good for bulk inserts&lt;/td&gt;
&lt;td&gt;Better for frequent queries&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  When Should You Use a Heap?
&lt;/h2&gt;

&lt;p&gt;A heap isn't better or worse than a clustered table—it depends on the workload.&lt;/p&gt;

&lt;p&gt;Typical scenarios where a heap works well include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ETL staging tables&lt;/li&gt;
&lt;li&gt;Bulk data imports&lt;/li&gt;
&lt;li&gt;Temporary processing tables&lt;/li&gt;
&lt;li&gt;Tables that are frequently truncated and reloaded&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In these situations, avoiding clustered index maintenance can improve insert performance.&lt;/p&gt;




&lt;h2&gt;
  
  
  When Should You Avoid a Heap?
&lt;/h2&gt;

&lt;p&gt;Heaps aren't ideal for every workload.&lt;/p&gt;

&lt;p&gt;Consider a clustered index if your table:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is frequently queried&lt;/li&gt;
&lt;li&gt;Performs range searches&lt;/li&gt;
&lt;li&gt;Requires ordered results&lt;/li&gt;
&lt;li&gt;Experiences frequent updates&lt;/li&gt;
&lt;li&gt;Supports an OLTP application&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Choosing the right storage structure should always depend on how the table is used.&lt;/p&gt;




&lt;h2&gt;
  
  
  Understanding Forwarded Records
&lt;/h2&gt;

&lt;p&gt;One concept every SQL Server DBA should know is &lt;strong&gt;Forwarded Records&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Imagine a row grows after an UPDATE and no longer fits on its original page.&lt;/p&gt;

&lt;p&gt;SQL Server may:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Move the row to another page.&lt;/li&gt;
&lt;li&gt;Leave a forwarding pointer behind.&lt;/li&gt;
&lt;li&gt;Follow that pointer whenever the row is accessed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Over time, too many forwarded records can increase I/O and reduce scan performance.&lt;/p&gt;

&lt;p&gt;If a heap experiences frequent updates, it's worth monitoring forwarded records as part of regular database maintenance.&lt;/p&gt;




&lt;h2&gt;
  
  
  Identifying Heap Tables
&lt;/h2&gt;

&lt;p&gt;The following query lists heap tables in the current database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;SchemaName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;TableName&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tables&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;schemas&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;schema_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;schema_id&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;OBJECTPROPERTY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;object_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'TableHasClustIndex'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  List All Heaps with Row Counts
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;OBJECT_SCHEMA_NAME&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;object_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;SchemaName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;OBJECT_NAME&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;object_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;TableName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;rows&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indexes&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;partitions&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;
&lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;object_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;object_id&lt;/span&gt;
&lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index_id&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Find Forwarded Records
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;OBJECT_NAME&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;object_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;TableName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;forwarded_record_count&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dm_db_index_physical_stats&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;DB_ID&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'DETAILED'&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;index_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Real-World Scenario
&lt;/h2&gt;

&lt;p&gt;Suppose you have a staging table that loads 150 million rows every night.&lt;/p&gt;

&lt;p&gt;The data is transformed, exported, and the table is truncated before the next load.&lt;/p&gt;

&lt;p&gt;Would you create a clustered index?&lt;/p&gt;

&lt;p&gt;Probably not.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;




&lt;h2&gt;
  
  
  SQL Server Heap Interview Prep
&lt;/h2&gt;

&lt;p&gt;&lt;/p&gt;
  What is a Heap?
  &lt;p&gt;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).&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  What is a RID?
  &lt;p&gt;RID stands for Row Identifier.&lt;/p&gt;

&lt;p&gt;It consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;File ID&lt;/li&gt;
&lt;li&gt;Page ID&lt;/li&gt;
&lt;li&gt;Slot ID&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  What are Forwarded Records?
  &lt;p&gt;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.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  When would you choose a Heap over a Clustered Index?
  &lt;p&gt;Heaps are useful for staging tables, ETL processes, bulk imports, and temporary tables where insert performance is more important than ordered data retrieval.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

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




&lt;h2&gt;
  
  
  Common Mistakes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Assuming heaps are always faster.&lt;/li&gt;
&lt;li&gt;Using heaps for heavily queried OLTP tables.&lt;/li&gt;
&lt;li&gt;Ignoring forwarded records.&lt;/li&gt;
&lt;li&gt;Creating unnecessary nonclustered indexes without considering maintenance costs.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

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




&lt;h2&gt;
  
  
  Discussion
&lt;/h2&gt;

&lt;p&gt;Have you used heaps in production?&lt;/p&gt;

&lt;p&gt;If so, what type of workload benefited the most? Have you ever encountered performance issues caused by forwarded records?&lt;/p&gt;

&lt;p&gt;I'd love to hear about your experience in the comments.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Database Deep Dive Series&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;📘 Part 1 – SQL Server Heaps ✅&lt;/p&gt;

&lt;p&gt;➡️ Next Article: &lt;strong&gt;Clustered Indexes – How SQL Server Organizes Data&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>sql</category>
      <category>database</category>
      <category>performance</category>
      <category>backend</category>
    </item>
    <item>
      <title>Database Deep Dive Series</title>
      <dc:creator>Namrata Khorjuwekar</dc:creator>
      <pubDate>Tue, 07 Jul 2026 03:55:04 +0000</pubDate>
      <link>https://dev.to/namrata_khorjuwekar_/database-deep-dive-series-570d</link>
      <guid>https://dev.to/namrata_khorjuwekar_/database-deep-dive-series-570d</guid>
      <description>&lt;p&gt;Welcome to the Database Deep Dive Series—a collection of articles designed to help database professionals strengthen their technical knowledge through practical examples and real-world scenarios.&lt;/p&gt;

&lt;p&gt;Whether you're a Database Administrator, Database Developer, Cloud Database Administrator, or simply passionate about database technologies, this series explores core concepts across modern database platforms.&lt;/p&gt;

&lt;p&gt;Each article focuses on a single topic and includes:&lt;/p&gt;

&lt;p&gt;📖 Concept Overview&lt;br&gt;
⚙️ How It Works&lt;br&gt;
💻 Practical SQL Scripts&lt;br&gt;
🎯 Interview Questions&lt;br&gt;
✅ Best Practices&lt;br&gt;
⚠️ Common Pitfalls&lt;br&gt;
💡 Real-World Scenarios&lt;/p&gt;

&lt;p&gt;The goal of this series is to simplify complex database concepts, share practical knowledge, and provide resources that are useful for both day-to-day database administration and technical interview preparation.&lt;/p&gt;

&lt;p&gt;I hope these articles help you build a deeper understanding of database technologies&lt;/p&gt;

</description>
      <category>database</category>
      <category>interview</category>
      <category>sql</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
