<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Tuned Instance Sharing a decade of database lessons, failures, and fixes."]]></title><description><![CDATA[Tuned Instance Sharing a decade of database lessons, failures, and fixes."]]></description><link>https://tunedinstance.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1593680282896/kNC7E8IR4.png</url><title>Tuned Instance Sharing a decade of database lessons, failures, and fixes.&quot;</title><link>https://tunedinstance.com</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 29 May 2026 20:37:12 GMT</lastBuildDate><atom:link href="https://tunedinstance.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Demystifying TempDB Allocation Contention: GAM, SGAM, and PFS Page Wars]]></title><description><![CDATA[In a high-throughput SQL Server environment, TempDB is often the most heavily utilized database on the instance. When applications rely intensely on temporary tables (#temp), table variables (@table),]]></description><link>https://tunedinstance.com/demystifying-tempdb-allocation-contention-gam-sgam-and-pfs-page-wars</link><guid isPermaLink="true">https://tunedinstance.com/demystifying-tempdb-allocation-contention-gam-sgam-and-pfs-page-wars</guid><category><![CDATA[infrastructure]]></category><category><![CDATA[TempDB]]></category><category><![CDATA[MSSQL]]></category><category><![CDATA[Performance Optimization]]></category><category><![CDATA[database]]></category><category><![CDATA[performance]]></category><dc:creator><![CDATA[rakeshkishore]]></dc:creator><pubDate>Fri, 29 May 2026 19:28:39 GMT</pubDate><content:encoded><![CDATA[<p>In a high-throughput SQL Server environment, TempDB is often the most heavily utilized database on the instance. When applications rely intensely on temporary tables (#temp), table variables (@table), or complex joins that spill to disk, TempDB can quickly become a massive operational bottleneck.</p>
<p>If you see performance degrading and find your sessions waiting on PAGELATCH_UP or PAGELATCH_EX resource types inside database ID 2, you are likely at war with TempDB allocation contention. Let's look at how the storage engine tracks space and how to eliminate this bottleneck permanently.</p>
<hr />
<h2>1. The Core Infrastructure: GAM, SGAM, and PFS</h2>
<p>To understand allocation contention, you must understand how SQL Server tracks data page availability. The engine allocates space in groups of 8 pages (each page is 8KB), known as an <strong>Extent</strong> (64KB). It uses three special system page types to manage this:</p>
<pre><code class="language-plaintext">+-----------------------------------------------------------------------+
|                       TEMPDB ALLOCATION TRACKING                      |
+-----------------------------------------------------------------------+
| [ GAM Page ]   --&gt; Tracks which extents are completely free or full.  |
| [ SGAM Page ]  --&gt; Tracks mixed extents containing unallocated pages. |
| [ PFS Page ]   --&gt; Tracks byte-level allocation status &amp; page fullness|
+-----------------------------------------------------------------------+
</code></pre>
<ul>
<li><p><strong>Global Allocation Map (GAM):</strong> Tracks which extents have been allocated. Each GAM page covers roughly 4GB of data file space.</p>
</li>
<li><p><strong>Shared Global Allocation Map (SGAM):</strong> Tracks extents currently used as "mixed extents" (extents shared by multiple small objects). Like GAM, each page tracks 4GB of space.</p>
</li>
<li><p><strong>Page Free Space (PFS):</strong> Tracks the allocation status and exact amount of free space inside individual pages. A PFS page occurs every 64MB (or every 8,000 pages).</p>
</li>
</ul>
<hr />
<h2>2. Why the Contention Happens</h2>
<p>Every time a session creates a temporary table, the storage engine must allocate a fresh page. It scans the first GAM/SGAM page to find an available extent, and then checks the PFS page to register the allocation.</p>
<p>When hundreds of concurrent application threads try to create and destroy temporary objects simultaneously, they all rush to modify the <strong>exact same allocation pages</strong> at the start of the TempDB data file.</p>
<p>Because only one thread can modify a memory page at an absolute microsecond, a massive queue forms. Threads stall, and your wait statistics show high PAGELATCH delays on resources like <code>2:1:1</code> (Database 2, File 1, Page 1 - GAM), <code>2:1:2</code> (SGAM), or <code>2:1:3</code> (PFS).</p>
<hr />
<h2>3. The Enterprise Remedy Checklist</h2>
<p>Modern versions of SQL Server have built-in defenses against these allocation wars, but you must ensure your configuration follows senior DBA best practices:</p>
<h3>File Multiplicity (The Standard Rule)</h3>
<p>Divide your TempDB data storage across multiple physical files of identical size.</p>
<ul>
<li><p><strong>The Guideline:</strong> Create <strong>8 data files</strong> if your server has 8 or more logical cores. If contention persists under extreme workloads, scale up in increments of 4 (e.g., 12 or 16 files).</p>
</li>
<li><p><strong>Why it works:</strong> SQL Server uses a proportional-fill round-robin algorithm. Spreading data across 8 files means you now have 8 GAM, 8 SGAM, and 8 PFS pages operating in parallel, splitting the thread workload cleanly.</p>
</li>
</ul>
<h3>Enable Native Behaviors (SQL 2016+)</h3>
<p>If you are running older legacy systems, ensure Trace Flags <strong>1117</strong> (Autogrow all files equally) and <strong>1118</strong> (Eliminate mixed extents, force uniform allocations) are active. In modern versions (SQL 2016 through 2025), these behaviors are permanently enabled by default under the hood.</p>
<h3>Metadata Optimization (SQL 2019+)</h3>
<p>If your contention is happening at the system catalog table layer rather than the storage pages, enable Memory-Optimized TempDB Metadata:</p>
<pre><code class="language-sql">ALTER SERVER CONFIGURATION SET MEMORY_OPTIMIZED TEMPDB_METADATA = ON;
-- Requires a SQL Server service restart to take effect
</code></pre>
<p>This shifts the tracking of TempDB system tables into lock-free, latch-free memory-optimized structures, completely eliminating system table latches.</p>
<hr />
<p><em>Have you run into TempDB page wars on your production environments? Let's discuss your tuning configurations in the comments below!</em></p>
]]></content:encoded></item><item><title><![CDATA[Conquering Parameter Sniffing: When Good Queries Go Bad]]></title><description><![CDATA[It is a scenario every database administrator knows too well: An application query has been running flawlessly for months, executing in milliseconds. Suddenly, users report a massive slowdown. You pul]]></description><link>https://tunedinstance.com/conquering-parameter-sniffing-when-good-queries-go-bad</link><guid isPermaLink="true">https://tunedinstance.com/conquering-parameter-sniffing-when-good-queries-go-bad</guid><category><![CDATA[querystore]]></category><category><![CDATA[T-SQL]]></category><category><![CDATA[parameter-sniffing]]></category><category><![CDATA[MSSQL]]></category><category><![CDATA[MSSQLDBA]]></category><category><![CDATA[# sqlserver]]></category><category><![CDATA[performance]]></category><category><![CDATA[Performance Tuning]]></category><dc:creator><![CDATA[rakeshkishore]]></dc:creator><pubDate>Fri, 29 May 2026 19:26:01 GMT</pubDate><content:encoded><![CDATA[<p>It is a scenario every database administrator knows too well: An application query has been running flawlessly for months, executing in milliseconds. Suddenly, users report a massive slowdown. You pull up the active sessions and find a critical business query consuming 100% CPU and causing timeouts.</p>
<p>You execute the underlying statement manually in SSMS, and it runs instantly. What is happening? You are dealing with the dual-edged sword of the relational engine: <strong>Parameter Sniffing</strong>.</p>
<hr />
<h2>1. Understanding the Mechanics</h2>
<p>When a parameterized query or stored procedure compiles for the first time, the SQL Server Query Optimizer does not compile it blindly. It "sniffs" the literal values passed during that initial execution.</p>
<p>Using those sniffed values, it references the database histograms (statistics) to estimate how many rows will return and builds a highly optimized execution plan tailored exactly for that data volume.</p>
<pre><code class="language-plaintext">+-------------------------------------------------------------------------+
|                        PARAMETER SNIFFING MALFUNCTION                   |
+-------------------------------------------------------------------------+
| [ Execution 1: Small Value ] --&gt; Compiles Nest Loop Plan (Fast)         |
| [ Execution 2: Large Value ] --&gt; Reuses Nested Loop Plan --&gt; TANK PLAN! |
+-------------------------------------------------------------------------+
</code></pre>
<p>The issue occurs when your data distribution is skewed:</p>
<ul>
<li><p><strong>The Good Cache:</strong> If the initial execution uses a rare parameter value, the optimizer creates a high-performance <strong>Index Seek + Nested Loops</strong> plan.</p>
</li>
<li><p><strong>The Regression:</strong> If the next user runs the procedure using a highly common parameter value that targets millions of rows, SQL Server reuses that cached plan. The engine attempts to process millions of rows using an index seek and loop operation meant for single digits, causing massive disk loops and high CPU usage.</p>
</li>
</ul>
<hr />
<h2>2. Advanced Triage Techniques</h2>
<p>When a query is actively regressing in production, you have several ways to resolve the issue depending on your version constraints.</p>
<h3>The Emergency Cache Flush</h3>
<p>If you need a quick fix to restore operational stability immediately without modifying code, clear the bad plan out of memory using the specific plan handle:</p>
<pre><code class="language-sql">-- Find the plan handle via sys.dm_exec_requests or Query Store, then clear it:
FREEPROCCACHE (0x060005008F4C6E12406198C2020000000000000000000000);
</code></pre>
<h3>The Query Store Safe Haven (SQL 2016+)</h3>
<p>If you have Query Store active, do not guess. Open the <strong>Regressed Queries</strong> dashboard, locate the execution plan that was running cleanly yesterday, and click <strong>Force Plan</strong>. This locks the safe execution blueprint into place, overriding the plan cache entirely.</p>
<hr />
<h2>3. Permanent Code Remediation Strategies</h2>
<p>To fix the root cause so the query remains stable indefinitely, refactor the T-SQL logic using one of these structural code techniques:</p>
<h3>Option A: The Optimize For Hint</h3>
<p>If 95% of your workload queries target a specific data density range, force the optimizer to always compile the plan using a balanced baseline parameter value, regardless of what the user types:</p>
<pre><code class="language-sql">SELECT OrderID, CustomerID, Status 
FROM Sales.Orders
WHERE CustomerID = @TargetCustomerID
OPTION (OPTIMIZE FOR (@TargetCustomerID = 1001));
</code></pre>
<h3>Option B: The Recompile Hint</h3>
<p>If the data volume varies wildly on every single execution and there is no "average" case, tell the engine to bypass the plan cache completely and compile a fresh plan for every run:</p>
<pre><code class="language-sql">CREATE OR ALTER PROCEDURE dbo.usp_GetCustomerData
    @CustomerID INT
AS
BEGIN
    SELECT * FROM dbo.Customers 
    WHERE CustomerID = @CustomerID
    OPTION (RECOMPILE); -- Low compilation overhead vs high runtime savings
END;
</code></pre>
<h3>Option C: Intelligent Query Processing (SQL 2022+)</h3>
<p>If you have upgraded your database compatibility level to SQL Server 2022, the engine addresses this problem natively via <strong>Parameter Sensitive Plan (PSP) Optimization</strong>. The engine automatically detects skewed parameters and caches <em>multiple</em> execution plans for a single query, routing traffic dynamically based on data size bounds.</p>
<hr />
<p><em>What strategy do you use to conquer parameter sniffing in your environments? Let's discuss code hints versus architectural fixes below!</em></p>
]]></content:encoded></item><item><title><![CDATA[The Evolution of SQL Server Architecture: From SQL 2005 to SQL 2025]]></title><description><![CDATA[Every time an application executes a T-SQL query, a highly coordinated sequence of events fires across the database engine. For senior database engineers, performance tuning isn't about guessing index]]></description><link>https://tunedinstance.com/the-evolution-of-sql-server-architecture-from-sql-2005-to-sql-2025</link><guid isPermaLink="true">https://tunedinstance.com/the-evolution-of-sql-server-architecture-from-sql-2005-to-sql-2025</guid><category><![CDATA[SQL]]></category><category><![CDATA[SQL Server]]></category><category><![CDATA[architecture]]></category><category><![CDATA[performance]]></category><category><![CDATA[database]]></category><category><![CDATA[MSSQL]]></category><category><![CDATA[mssqlserver]]></category><dc:creator><![CDATA[rakeshkishore]]></dc:creator><pubDate>Fri, 29 May 2026 19:03:50 GMT</pubDate><content:encoded><![CDATA[<p>Every time an application executes a T-SQL query, a highly coordinated sequence of events fires across the database engine. For senior database engineers, performance tuning isn't about guessing indexes; it is about understanding how the architectural framework handles memory, threads, locks, and storage.</p>
<p>While marketing teams talk about features, true DBAs focus on the structural evolution of the engine. Let's trace the deep architectural shifts in Microsoft SQL Server over the past two decades—from the foundational rewrite of SQL 2005 to the AI-native, highly concurrent engine of SQL 2025.</p>
<h2>1. The Core Foundational Architecture</h2>
<p>Before examining how the engine has changed, we must review the foundational layers that have governed SQL Server across every version. The engine is divided into three primary structural layers operating above a specialized user-mode operating system.</p>
<h3>The Network Interface (SNI) &amp; Protocol Layer</h3>
<p>Every communication begins with the <strong>SQL Server Network Interface (SNI)</strong> layer. It accepts incoming Tabular Data Stream (TDS) packets wrapped in network protocols like TCP/IP, Named Pipes, or Shared Memory, unpacking the raw T-SQL command strings for processing.</p>
<h3>The Relational Engine (The Brain)</h3>
<p>Also known as the Query Processor, this engine determines <em>how</em> a query should execute:</p>
<ul>
<li><p><strong>Parser &amp; Algebrizer:</strong> Checks syntax, validates object mappings, and creates a logical query tree.</p>
</li>
<li><p><strong>Query Optimizer:</strong> Evaluates cost-based models, indexes, and statistics to produce an optimal execution plan.</p>
</li>
<li><p><strong>Plan Cache:</strong> Stores compiled plans in RAM to skip compilation overhead on subsequent queries.</p>
</li>
</ul>
<h3>The Storage Engine (The Muscle)</h3>
<p>This engine manages data access, concurrency, and file interaction:</p>
<ul>
<li><p><strong>Buffer Pool / Buffer Manager:</strong> Manages the 8KB pages inside memory. It handles logical reads from the data cache and schedules physical reads from storage.</p>
</li>
<li><p><strong>Transaction Manager:</strong> Guarantees ACID properties using the Write-Ahead Logging (WAL) protocol via the Lock Manager and Log Manager.</p>
</li>
</ul>
<h3>SQLOS: The Micro-OS</h3>
<p>Sitting directly between the database engine and the Windows/Linux operating system is <strong>SQLOS</strong>. This user-mode scheduling application handles memory allocation, thread scheduling (via non-preemptive workers), and latch synchronization without incurring the high context-switching overhead of the underlying host OS.</p>
<h2>2. The Architectural Timeline: 2005 to 2025</h2>
<p>Every major release of SQL Server has shifted how these core components interact under heavy enterprise workloads.</p>
<table style="min-width:75px"><colgroup><col style="min-width:25px"></col><col style="min-width:25px"></col><col style="min-width:25px"></col></colgroup><tbody><tr><td><p><strong>SQL Server Version</strong></p></td><td><p><strong>Landmark Architectural Shift</strong></p></td><td><p><strong>Technical Impact</strong></p></td></tr><tr><td><p><strong>SQL Server 2005</strong></p></td><td><p>Introduction of SQLOS &amp; DMV Infrastructure</p></td><td><p>Replaced old User Mode Scheduling (UMS). Completely rewrote internal management and exposed engine state via Dynamic Management Views (DMVs).</p></td></tr><tr><td><p><strong>SQL Server 2012</strong></p></td><td><p>Always On Availability Groups &amp; Column store</p></td><td><p>Shifted database recovery and high availability away from shared-disk architectures (FCIs) to shared-nothing database-level replication.</p></td></tr><tr><td><p><strong>SQL Server 2014</strong></p></td><td><p>In-Memory OLTP (Hekaton)</p></td><td><p>Introduced a lock-free, latch-free concurrency model using multi-version concurrency control (MVCC) and natively compiled stored procedures.</p></td></tr><tr><td><p><strong>SQL Server 2016</strong></p></td><td><p>Query Store Telemetry</p></td><td><p>Embedded a flight data recorder directly into the database file, altering the plan cache paradigm to persist runtime performance history.</p></td></tr><tr><td><p><strong>SQL Server 2017</strong></p></td><td><p>Platform Abstraction Layer (SQLPAL)</p></td><td><p>Decoupled the engine from Windows. SQLPAL allowed the engine to run natively on Linux containers by abstracting OS API calls.</p></td></tr><tr><td><p><strong>SQL Server 2022</strong></p></td><td><p>Intelligent Query Processing (IQP)</p></td><td><p>Turned the Relational Engine into an adaptive framework that fixes bad plans dynamically using parameter-sensitive feedback.</p></td></tr><tr><td><p><strong>SQL Server 2025</strong></p></td><td><p>Native AI Store &amp; Transaction ID (TID) Locking</p></td><td><p>Eliminates middleware for vector searches using <strong>DiskANN</strong> indexes, while implementing thread-level optimized locking to reduce high-concurrency memory pressure.</p></td></tr></tbody></table>

<h2>3. Deep-Diving the Major Architectural Turning Points</h2>
<h3>SQL 2005: The Birth of Modern Telemetry</h3>
<p>SQL 2005 was the release that completely severed any remaining architectural ties to old Sybase code structures. By building <strong>SQLOS</strong>, Microsoft gave database administrators total control over memory nodes and non-preemptive thread workers. More importantly, it introduced <strong>DMVs</strong> (like <a href="http://sys.dm"><code>sys.dm</code></a><code>_exec_requests</code> and <a href="http://sys.dm"><code>sys.dm</code></a><code>_os_wait_stats</code>), illuminating what was previously a complete black box.</p>
<h3>SQL 2014: Breaking the Disk Bottleneck with MVCC</h3>
<p>Traditional relational tables rely heavily on locks and latches to maintain consistency, which chokes performance under extreme concurrency. SQL 2014 introduced the <strong>Hekaton In-Memory OLTP</strong> engine. By using memory-optimized structures where rows are linked via lock-free pointer arrays, threads modify rows concurrently using Multi-Version Concurrency Control (MVCC), eliminating execution blocks.</p>
<h3>SQL 2017: Going Cross-Platform with SQLPAL</h3>
<p>To make SQL Server run on Linux and Docker without rewriting millions of lines of C++ code, Microsoft engineered the <strong>SQL Platform Abstraction Layer (SQLPAL)</strong>. SQLPAL acts as a wrapper that maps SQLOS calls directly to Linux system calls, preserving identical execution mechanics across different operating systems.</p>
<h3>SQL 2025: Vector Pipelines &amp; Optimized Locking</h3>
<p>The architectural focus of modern database engineering centers on horizontal cloud scaling, high concurrency, and AI workloads. SQL Server 2025 fundamentally alters the storage and locking layers:</p>
<ul>
<li><p><strong>Vector Integration:</strong> The Storage Engine introduces a native vector data type alongside <strong>DiskANN (Approximate Nearest Neighbor)</strong> search indexes. Similarity searches and semantic analytical processing now happen right at the source of record instead of requiring external vector middleware.</p>
</li>
<li><p><strong>Transaction ID (TID) Locking:</strong> Inspired by highly resilient Azure SQL database designs, SQL 2025 minimizes traditional page and row locking overhead in heavy write environments, dramatically mitigating memory contention and blocking chains for concurrent users.</p>
</li>
</ul>
]]></content:encoded></item></channel></rss>