This is the 4th in a series of posts about query plans.  The first post covered what a query plan is and how to read it.  The second post described the effort required to make a query plan.  The third entry explained how the plans are stored in a cache to be reused.  This post will cover how the optimizer is able to quickly determine whether a plan in the cache exists for any given query. When a query is executed the database engine quickly creates a hash of the query code.  This hash is called a query handle.  The engine then compares this handle to a listRead More →

The previous post in this series introduced the idea of query execution plans.  These plans are compiled by the SQL Server optimizer when a query is executed in an effort to decide an efficient manner in which to execute a query.  This compilation takes time and effort beyond that of actually running the query.  While most compilation effort is relatively small, at times it can be significant and be an impetus to query performance.  In this post we’ll offer methods to measure that time and effort. The demos below utilize the WideWorldImporters DB that can be downloaded for free. To follow along open SSMS, create a new queryRead More →

This post will serve as the first in a series of posts about query execution plans.  In this entry the goal is simply to understand that query execution plans exist, why they exist, and how to do basic navigation of them in SSMS. Every time a query is executed on a SQL Server instance the server must decide how best to find the necessary data to be retrieved or modified.  It’s not as simple as going to a table and returning rows.  A table may have multiple indexes and the decision must be made about which, if any, is appropriate for this query.  There mightRead More →

I was working on a project this week and stumbled across an issue I hadn’t seen before. The programmer had written stored procedures for every possible CRUD operation as well as all reporting requirements. Security was controlled by granting EXECUTE permissions only to appropriate stored procedures and by explicitly not granting permission to any tables or views within the database. One of the procedures was getting a bad query plan and timing out. This is when I was called in. The procedure was performing a search based on an unknown number of up to 10 search parameters. The code was filled with many AND/OR combinationsRead More →

Even the most green DBAs know that indexes are a good thing.  A database won’t run well without them.  But it is important to remember that indexes aren’t free.  They have to be created, stored, backed up, consistency checked, updated, defragmented, and have their statistics updated.  That’s a lot of work!  This extra work associated with indexes is sometimes called the “write penalty”.  It is why having too many indexes can be just as bad as not having enough. The goal of the DBA should be to have as many high-value indexes — indexes that will be used often by the workload — as possibleRead More →

If you read my last post, you’ll find this to the be exact opposite.  Instead of determining the best way to find rows that exist in one dataset but not another, we’ll be looking for rows that exist in 2 different datasets. The obvious answer is a join statement, but does that always perform the best?  Certainly, if you require other fields from the secondary table then a join will always be best.  For this test we are looking for rows that appear in a table called orderheader that are also in a temporary table called #ords.  The field that we are comparing is anRead More →

It is a pretty common need to find rows that exist in one dataset, but not in another.  The question I will look to answer today is, “which way is best?”.  For this test we are looking for rows that appear in a table called orderheader that aren’t also in a temporary table called #ords.  The field that we are comparing is an INT called ord_hdrnumber and it is the Clustered Primary Key of each table. We’ll compare the pros, cons, and performance of 4 popular methods to complete the task.   –NOT IN SELECT a.ord_hdrnumber FROM orderheader a WHERE a.ord_hdrnumber NOT IN (SELECT b.ord_hdrnumberRead More →