Problem Description / Requirement

Your customer is using new software in the company. This software uses its own logic for protocol measures and locks because – presumably – the concept of intelligent locking is not known.

Before each query is called, the name of the object used, along with the time stamp and user name, is entered in the [dbo].[locks] table. As soon as the process is finished, the entry is removed again. The customer notices that after about 1 hour, access to the [dbo].[locks] table becomes so slow that the application shows noticeable failure symptoms.

Through “trial and error” it was determined that a REBUILD INDEX on the table causes the application to behave as usual again. For this reason, the customer has implemented an SQL Agent job in its system that rebuilds all indexes in the [dbo].[locks] table once an hour. Since the table is not very large, the job is executed for the application without any problems.
The vendor has no idea why this behavior occurs.

The typical statement: “You are the only customer experiencing this behavior”

Challenge

The customer contacts you for a root cause analysis of the behavior because the manufacturer has no explanation for it. Your task is:

  • to find out why the performance on the table is continuously decreasing although only a few records are stored..
  • to work out a solution to maintain consistent performance.

Condition

  • You can use indexes of your choice for the table [dbo].[locks].
  • You can customize the stored procedure for the stress test (see below) as you wish
  • The metadata of the table must NOT be changed!
Technical Information

The challenge creates two objects in your database:

  • Table [dbo].[locks]
  • Stored procedure: [dbo].[SQLQueryStress_stress_test]

The table [dbo].[locks] contains a maximum of 200 records, which are continuously deleted by the stored procedure and then added again.
This is intended to simulate a workload that represents many users and accesses.

How to start the challenge

When you are connected to the SQL Server instance, run the following commands:

EXECUTE sqlchallenge.dbo.create_challenge 'list';
will give you a list of open challenges
EXECUTE sqlchallenge.dbo.create_challenge 'name_of_challenge';
will create the challenge for you

The SQLQueryStress tool is recommended for simulating the workload.

https://github.com/ErikEJ/SqlQueryStress

For this challenge, I have provided a template for SQLQueryStress that already has all settings (except the database name) preset.

Before loading the template, simply replace the name of the database in the JSON file with your own database (generated when the challenge is created). The template can then be loaded.

Note:

When you start SQLQueryStress note the increasing values of

  • “Logical Reads”
  • “Actual Seconds/Iteration (Avg)”

SQLQueryStress with presettings for sqlchallenge 6

SQLQueryStress - JSON Template
{
  "CollectIoStats":true,
  "CollectTimeStats":true,
  "CommandTimeout":0,
  "ConnectionTimeout":15,
  "DelayBetweenQueries":0,
  "EnableConnectionPooling":true,
  "ForceDataRetrieval":false,
  "KillQueriesOnCancel":true,
  "MainDbConnectionInfo":
  {
    "AdditionalParameters":"",
    "ApplicationIntent":0,
    "AzureMFA":false,
    "ConnectTimeout":15,
    "Database":"REPLACE THIS STRING WITH THE NAME OF YOUR DATABASE",
    "EnablePooling":true,
    "EncryptOption":"True",
    "IntegratedAuth":false,
    "Login":"sqlchallenge",
    "MaxPoolSize":2,
    "Password":"sqlchallenge#2025!",
    "Server":"sqlchallenges.germanywestcentral.cloudapp.azure.com",
    "TrustServerCertificate":true
},
"MainQuery":"EXEC dbo.SQLQueryStress_stress_test @table_name = @table_name;",
"NumIterations":100000,
"NumThreads":20,
"ParamDbConnectionInfo":
{
    "AdditionalParameters":"",
    "ApplicationIntent":0,
    "AzureMFA":false,
    "ConnectTimeout":0,
    "Database":"",
    "EnablePooling":true,
    "EncryptOption":"False",
    "IntegratedAuth":true,
    "Login":"",
    "MaxPoolSize":0,
    "Password":"",
    "Server":"(local)",
    "TrustServerCertificate":false
},
"ParamMappings":
[
{"Key":"@table_name",
"Value":"table_name"}
],
"ParamQuery":"SELECT table_name FROM dbo.locks;",
"ShareDbSettings":true
}
customer expectations

The customer wants to know why the observed behavior occurs. As a result, the SQL Agent job with its hourly execution should be deactivated in order to make the resources available for other tasks.

Solution

This challenge is much more complicated because several components of Microsoft SQL Server interact with each other.
– Read Committed Snapshot Isolation
– NONSargable arguments for the WHERE clause
– Incorrect indexes

If you want to know where the problem lies with this challenge, you can click on the link below.

SQL Challenge #6 – Solution

Connect to Microsoft SQL Server

SQL Server: sqlchallenges.germanywestcentral.cloudapp.azure.com
Port: 1433
Version:
16.0.4165.4
Edition: Developer Edition
Authentication Type: SQL Server Authentication
Login Name: sqlchallenge
Password: sqlchallenge#2025!
Encryption Mandatory
Trust Server Certificate: True

 

Improve Your Skills as Query Tuner for SQL Server

During this workshop, you’ll gain the expertise and confidence needed to diagnose and fine-tune slow-performing queries, resulting in improved database responsiveness and end-user satisfaction. Whether you’re an experienced database administrator, developer, or data analyst, this workshop will equip you with the knowledge and practical skills to tackle the most challenging query optimization tasks.

Improve your skills as a database developer
Improve Your Skills as a Database Developer for SQL Server

In this workshop, we will cover a wide range of topics and techniques that are essential for modern database developers working with SQL Server. From fundamental concepts to advanced best practices, you’ll gain the knowledge and practical experience needed to excel in your role.