---
title: "11 Amazing Performance Tuning in SQL Server Tips"
description: "Is your SQL server starting to slow down? Learn all about performance tuning in SQL server in this tutorial!"
canonical: "https://adamtheautomator.com/performance-tuning-in-sql-server/"
---

# 11 Amazing Performance Tuning in SQL Server Tips

> Is your SQL server starting to slow down? Learn all about performance tuning in SQL server in this tutorial!

Source: https://adamtheautomator.com/performance-tuning-in-sql-server/

---

ATA Learning

Tap to hide

[

ATA Learning

](/)

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Search for:  

*   [](https://twitter.com/adbertram)
*   [](https://github.com/Adam-the-Automator)
*   [](https://www.linkedin.com/company/adam-the-automator-llc)
*   [](/feed/)

![11 Amazing Performance Tuning in SQL Server Tips](https://adamtheautomator.com/wp-content/uploads/2021/09/How-to-Tune-Your-SQL-Server-for-Performance.jpg)

# 11 Amazing Performance Tuning in SQL Server Tips

[![](https://secure.gravatar.com/avatar/375d1594d4bdf138ea2280401ba7f36513ca9e5ef259e44e5c5359d2127cf297?s=192&d=mm&r=g)Joydip Kanjilal](https://adamtheautomator.com/author/joydip-kanjilal/)17 September 20218 min. read

Categories: [IT Ops](/category/it-ops/)

Tags:[Microsoft SQL Server](/tag/microsoft-sql-server/)

Table of Contents

*   [Prerequisites for Performance Tuning in SQL Server](#prerequisites-for-performance-tuning-in-sql-server)
*   [Normalize Your Databases](#normalize-your-databases)
*   [Create an Execution Plan](#create-an-execution-plan)
*   [Monitor Resource Usage with Performance Monitor](#monitor-resource-usage-with-performance-monitor)
*   [Separate Data and Log Files](#separate-data-and-log-files)
*   [Reduce Temporary Tables](#reduce-temporary-tables)
*   [Use Indexes Religiously](#use-indexes-religiously)
*   [Avoid Correlated Sub Queries](#avoid-correlated-sub-queries)
*   [Avoid SELECT \* in a Query](#avoid-select--in-a-query)
*   [Avoid Queries Inside Loops](#avoid-queries-inside-loops)
*   [Avoid Shrinking Data Files](#avoid-shrinking-data-files)
*   [Determine Performance Bottlenecks](#determine-performance-bottlenecks)
*   [Memory bottlenecks](#memory-bottlenecks)
*   [I/O Bottlenecks](#io-bottlenecks)
*   [CPU bottlenecks](#cpu-bottlenecks)
*   [Conclusion](#conclusion)

A SQL Server database is a wonderful piece of storage technology when it’s working well. But, when performance starts to degrade, not so much; if queries are slow or workloads experience deadlocks or latency issues, an application’s performance will degrade. In this tutorial, you’ll learn tips and tricks for performance tuning in SQL server!

Let’s get started.

## Prerequisites for Performance Tuning in SQL Server

All demos performed in this tutorial were done on [SQL Server 2019 Developer Edition](https://www.microsoft.com/en-gb/sql-server/sql-server-downloads) (free edition), but older versions, such as SQL Server 2014 or SQL Server 2016, should work also.

## Normalize Your Databases

A good database design helps maintain data integrity. A [normalized database](https://docs.microsoft.com/en-us/office/troubleshoot/access/database-normalization-description) can reduce the quantity of duplicated data considerably, simplifying read and write operations. Proper usage of foreign keys and primary [constraints](https://docs.microsoft.com/en-us/sql/relational-databases/tables/primary-and-foreign-key-constraints?view=sql-server-ver15) can also improve performance greatly.

Note that there are two types of constraints that can ensure data integrity – primary and foreign keys. A foreign key constraint states that the key may only contain values found in the referenced primary key, thus enforcing referential integrity.

But, keep in mind that performance will degrade if your databases have been normalized too much. Why? Because the more you normalize a database, the more tables you’ll create. As a result, there would be too many joins, which will impact performance.

You must select the appropriate and optimized data types when designing your database tables while considering the data stored in your database tables.

Related:[Understanding SQL Server Data Types (And When to Use Them)](https://adamtheautomator.com/sql-server-data-types/)

For example, rather than keeping a file itself, allow the file to reside in the file system and store the file path in your database table instead. Assume that you have a file named Test.txt in the root directory of the D:\\> drive.

You can allow the file to be physically stored in the disk and its path stored in the database.

## Create an **Execution Plan**

Knowledge is key, and knowing how a query performs can provide a ton of insight. One way to gain that insight is via an [execution plan](https://www.sqlshack.com/execution-plans-in-sql-server/). An execution plan is a graphical illustration of the [SQL Server Query Optimizer](https://www.red-gate.com/simple-talk/databases/sql-server/performance-sql-server/the-sql-server-query-optimizer/), the SQL Server’s built-in feature to naturally increase performance.

An execution plan lays outs performance information for a query working in conjunction with the query optimizer.

To generate an execution plan:

1.  Open SQL Server Management Studio
2.  Create a database query.
3.  Press the Ctrl+M keys to open the execution plan tab in the query window.

You’ll see below that the execution plan provides a lot of useful performance information about the query, such as the [Clustered Index Seek](https://sqlserverfast.com/epr/clustered-index-seek/) or Scan results, estimated CPU and I/O costs, the estimated number of rows for each execution of the query, row size, estimated, etc.

![Reviewing a SQL Execution Plan](https://adamtheautomator.com/wp-content/uploads/2021/09/image-115.png)

Reviewing a SQL Execution Plan

## **Monitor Resource Usage with Performance Monitor**

If your server can’t handle the load SQL Server puts on it, overall performance will suffer. You can monitor resource usage using the [System Monitor tool](https://techcommunity.microsoft.com/t5/windows-admin-center-blog/introducing-the-new-performance-monitor-for-windows/ba-p/957991) (Performance Monitor) and [performance counters](https://docs.microsoft.com/en-us/sql/relational-databases/performance/server-performance-and-activity-monitoring?view=sql-server-ver15).

Related:[How to Build a SQL Server Performance Monitor Script](https://adamtheautomator.com/sql-server-performance-monitor/)

Performance counters allow you to track in real-time resources the [SQL](https://adamtheautomator.com/sql-server-performance-monitor/) Server is consuming, such as memory, disk I/O, CPU, and more. To start Performance Monitor, run _perfmon.exe_. In the Performance Monitor application, you should [set up at least these below counters](https://www.windowscentral.com/how-use-performance-monitor-windows-10):

*   Memory: Available MBytes
*   Physical Disk: Avg. Disk sec/Read and Avg. Disk sec/Write
*   Processor: % Processor Time
*   SQL Server: Batch Requests/sec, Buffer cache hit ratio, and Compilations/sec

You can find many SQL Server-specific performance counters in the [SQL Server documentation](https://docs.microsoft.com/en-us/sql/integration-services/performance/performance-counters?view=sql-server-ver15).

Create a [baseline](https://www.sentryone.com/white-papers/performance-baselines-and-benchmarks-for-microsoft-sql-server) for resource usage (CPU, memory, and disk I/O) and set alerts and thresholds appropriately. A baseline is a known value used to compare subsequent measurements and performance. For example, 60–70 beats per minute are considered a good baseline for a middle-aged individual.

Similarly, you may establish a performance baseline by tracking performance indicators over a while and comparing them to previous results.

## **Separate Data and Log Files**

An SQL Server database must contain a minimum of two files: a data file and a log file. The data files comprise stored procedures, indexes, tables, and views, while the log file contains information needed for all database transactions recovery.

Ensure that [data and log files are kept on separate drives](https://docs.microsoft.com/en-us/sql/relational-databases/policy-based-management/place-data-and-log-files-on-separate-drives?view=sql-server-ver15). The primary goal of this technique is to isolate random and sequential access to data while generating the transaction logs. If the data and log files are on the same drive, there can be [increased I/O contention](https://docs.microsoft.com/en-us/sql/relational-databases/policy-based-management/place-data-and-log-files-on-separate-drives?view=sql-server-ver15) between them, resulting in performance degradation.

I/O contention occurs when more than one thread competes for the same I/O resources resulting in performance degradation. You might encounter I/O contention when there are many reads and writes, causing latency and bottlenecks.

When the number of your transactions grows, with the data and log files in separate drives, you will be taken aback at how much difference this approach makes.

The [access patterns of data and log files](https://www.varonis.com/blog/sql-server-best-practices-part-configuration) in SQL Server are different. While the data file is accessed predominantly randomly, the log file is accessed in sequential order. Now, for random read and write access, the disk storage needs the disk head re-positioned.

Separating files with varying access patterns enables disc head motions to be minimized, thus optimizing storage efficiency. This is why access to sequential data (in the log files) is much more efficient than accessing random data.

## **Reduce Temporary Tables**

[Temporary tables](https://www.sqlshack.com/overview-and-performance-tips-of-temp-tables-in-sql-server/) are great at storing data temporarily as your working with them but doing so only makes queries more complex. If you found yourself using the [Tem](https://www.sentryone.com/tempdb-in-sql-server)[p](https://www.sentryone.com/tempdb-in-sql-server)[DB](https://www.sentryone.com/tempdb-in-sql-server) a lot, for example, you should verify if you really need to. You may find yourself in a state of conflict with internal structures associated with the tempdb files.

If you have to use temp tables, you should build an index inside the temp tables to enhance the performance. You shouldn’t wait for the temp tables to be deleted automatically after use; instead, you should delete them as soon as you’re done using them.

## **Use Indexes Religiously**

An index is a data structure used to expedite data retrieval operations on a database table. Proper usage of indexes can improve data retrieval performance considerably. Creating appropriate indexes for your database is one of the [most important steps you can undertake in performance optimization](https://docs.microsoft.com/en-us/sql/relational-databases/indexes/reorganize-and-rebuild-indexes?view=sql-server-ver15).

Indexes are handy because they allow fast random look-ups and locate data that requires fewer disk I/O operations and low system resource consumption.

Before you can build effective indexes, it is critical to understand the type of queries and execution frequency. Additionally, if too many inserts, update, and delete operations are performed on your database tables, indexing may degrade performance.

At a glance, here are a few guidelines you should follow for using indexes properly:

*   Avoid creating indexes on small tables
*   It is a good practice to delete indexes that are no longer in use or used sparingly
*   Avoid indexing a column that has few unique values
*   You should check indexes to determine if they have been fragmented and then rebuild them
*   Ensure that your queries are making the best use of indexes
*   If you’re creating indexes on multiple columns, take into consideration how the columns will be queried

## Avoid **Correlated Sub Queries**

A correlated subquery (also known as a synchronized subquery) is a query nested within another query that utilizes values from the outer query to work. The subquery may have to be evaluated individually for each row processed by the outer query so that execution may be time-consuming.

A [correlated subquery](https://docs.microsoft.com/en-us/sql/relational-databases/performance/subqueries?view=sql-server-ver15) utilizes the values from the parent or the outer query. Hence, it executes row-by-row once for each row returned by the outer query, which decreases the SQL query performance. Below is an example of a correlated sub-query:

In this example, the inner query (`Select DepartmentName`) executes once for each row returned by the outer query (`Select e.FirstName`). You’re reading the Department table for each record of the Employee table – this will degrade performance.

```sql
Select e.FirstName,
e.LastName,
(Select DepartmentName FROM Department WHERE Id = e.DepartmentID) AS DepartmentName
From Employee e
```

To fix the issue with the correlated sub-query, you can refactor the code, as shown below:

Below, the query reads the Department table only once and joining with the Employee table, which is a much more efficient query. This query is proof that using correlated sub-queries is a big NO.

```sql
Select e.FirstName,
e.LastName,
d.DepartmentName
From Employee e
Left Outer Join Department d
On e.DepartmentId = d.DepartmentId
```

## **Avoid `SELECT *` in a Query**

A query in SQL Server runs faster when returning fewer data, so be sure to avoid using `SELECT *` and specify only the columns you want to return from a query. Fine-tuning a query is an important step you can take to tackle performance issues in SQL Server.

As an example, if you need only the `ProductId` and `ProductName` from the `Product` table, you should use the following query:

```sql
SELECT ProductId, ProductName from Product
```

And not this query below.

```sql
SELECT * FROM Product
```

## **Avoid Queries Inside Loops**

Writing queries inside loops results to degrading application performance because of repeated database access. So be sure to avoid writing queries inside loops.

Take a loop at the example code below that runs queries inside a loop. The query inserts 100 records in a table named MyTable.

```csharp
for(int i=0; i < 100; i++)
{
SqlCommand sqlCommand = new SqlCommand("Insert into MyTable (FirstColumn,
SecondColumn, ThirdColumn) Values (.....)";
sqlCommand.ExecuteNonQuery();
}
```

The fix to this is [moving the queries outside of the loops](https://codeutopia.net/blog/2010/10/07/optimizing-sql-removing-queries-inside-loops/). If you’re to speed up inserting a lot of data, you can batch your rows using a single insert statement as shown below:

```sql
INSERT INTO some_table (FirstColumn, SecondColumn, ThirdColumn)
VALUES ('row1-value1', 'row1-value2', 'row1-value3'),
('row2-value1', 'row2-value2', 'row2-value2'),
('row3-value1', 'row3-value2', 'row3-value2'),
(... etc etc ...)
```

## **Avoid Shrinking Data Files**

Reclaiming space by [shrinking data files](https://docs.microsoft.com/en-us/sql/relational-databases/databases/shrink-a-database?view=sql-server-ver15) is possible, which is accomplished by shifting data pages from one end of the file to an empty area nearer to the beginning of the file.

But, [shrinking data files in SQL Server hurts performance](https://www.sqlskills.com/blogs/paul/why-you-should-not-shrink-your-data-files/). Let’s understand why it is so. Shrinking creates index fragmentation, which is expensive in terms of locking, I/O, and transaction log generation, leading to poor performance.

If you need to shrink your data files, you must consider the performance impact before you do it. You should shrink your data files in rare cases, if at all.

## **Determine Performance Bottlenecks**

The term bottleneck implies performance degradation of SQL Server. The CPU utilization, memory utilization, and disk usage are common performance bottlenecks in SQL Server.

Below are some of the common symptoms you will observe when a bottleneck occurs:

*   Long I/O wait times
*   Increased query execution time
*   Increased disk activity
*   Increased CPU and memory utilization

### **Memory bottlenecks**

Memory bottlenecks are a result of insufficient memory resources available to your SQL Server instance. The SQL Server will attempt to write data to disk to free up the memory space to load new data onto the memory. When this occurs frequently, performance will eventually degrade.

To avoid memory bottlenecks, you can take advantage of a [query optimizer](https://docs.microsoft.com/en-us/sql/relational-databases/query-processing-architecture-guide?view=sql-server-ver15) to avoid using unnecessary or non-performant queries.

### **I/O Bottlenecks**

I/O bottlenecks are a result of inadequate storage available for supporting regular database operations. It occurs when SQL Server needs to load a large amount of data from the disk, thus saturating the I/O channels.

You can avoid I/O bottlenecks by [setting up monitoring, alerts, and threshold limits](https://docs.microsoft.com/en-us/sql/relational-databases/performance/set-up-a-sql-server-database-alert-windows?view=sql-server-ver15) appropriately so that you can determine when to limit reading or writing database pages to and from the disk.

### **CPU bottlenecks**

CPU bottlenecks occur due to insufficient hardware resources in your computer. It can happen when SQL Server needs to process too many queries at the same point in time.

When CPU bottlenecks occur, your queries wait before they can be processed. You can check the logs to determine whether your SQL Server instance is using excessive CPU cycles. You should optimize the execution plan of the queries to reduce CPU usage and avoid bottlenecks. You can know the top CPU-consuming sessions from SSMS.

You can configure performance monitor to [determine CPU consumption](https://www.mssqltips.com/sqlservertip/1475/setup-performance-monitor-to-always-collect-sql-server-performance-statistics/) in your computer.

Take advantage of tools such as [SQL Profiler](https://docs.microsoft.com/en-us/sql/tools/sql-server-profiler/sql-server-profiler?view=sql-server-ver15) to retrieve the complete T-SQL activity of SQL Server. You can also leverage Dynamic Management Views (DMVs) to determine server restarts and memory pressure.

## **Conclusion**

This tutorial has given you a head-start into SQL server performance tuning. You’ve learned the importance of performance tuning in SQL Server and how to apply each technique. You can now keep your SQL server at its prime performance, from creating execution plans to determining the bottlenecks.

Now which technique piqued your interest the most? How would you make your own performance tuning strategy?

Share this article

[Share on X](https://twitter.com/intent/tweet?url=https%3A%2F%2Fadamtheautomator.com%2Fperformance-tuning-in-sql-server%2F&text=11%20Amazing%20Performance%20Tuning%20in%20SQL%20Server%20Tips)[Share on Facebook](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fadamtheautomator.com%2Fperformance-tuning-in-sql-server%2F)[Share on LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fadamtheautomator.com%2Fperformance-tuning-in-sql-server%2F)

## Related Posts

![](https://adamtheautomator.com/wp-content/uploads/2024/03/mssql-linux.jpg)

### [How to Install Microsoft SQL Server on Linux](/mssql-linux/)

Unlock the potential of Microsoft SQL (MSSQL) on Linux systems in solving database management challenges effortlessly!

![](https://adamtheautomator.com/wp-content/uploads/2022/09/Getting-Started-With-Microsoft-SQL-Server-Standard-Edition.jpg)

### [Getting Started With Microsoft SQL Server Standard Edition](/microsoft-sql-server-standard-edition/)

Learn how to get started with databases via the Microsoft SQL Server Standard Edition in this tutorial from ATA Learning!

![](https://adamtheautomator.com/wp-content/uploads/2021/07/Understanding-SQL-Server-Data-Types-And-When-to-Use-Them.jpg)

### [The Amazing SQL Server Data Types (And When to Use Them)](/sql-server-data-types/)

If you’re storing SQL data, you must understand SQL Server data types. In this article, you’ll learn about all data types and when to use them.

## Categories

*   [IT Ops](/category/it-ops/)
*   [Cloud](/category/cloud/)
*   [DevOps](/category/devops/)
*   [Home Ops](/category/home-ops/)
*   [Information Security](/category/infosec/)
*   [Software Development](/category/software-development/)

## Site

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Copyright 2026© ATA Learning | [Privacy Policy](/privacy/)
