<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://sqlblog.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Search results matching tags 'sp_whoisactive' and 'month of monitoring'</title><link>http://sqlblog.com/search/SearchResults.aspx?o=DateDescending&amp;tag=sp_whoisactive,month+of+monitoring&amp;orTags=0</link><description>Search results matching tags 'sp_whoisactive' and 'month of monitoring'</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>Twenty Nine Days of Activity Monitoring (A Month of Activity Monitoring, Part 30 of 30)</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2011/04/30/twenty-nine-days-of-activity-monitoring-a-month-of-activity-monitoring-part-30-of-30.aspx</link><pubDate>Sat, 30 Apr 2011 14:00:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:35301</guid><dc:creator>Adam Machanic</dc:creator><description>&lt;p&gt;&lt;i&gt;This post is part 30 of a 30-part series about the &lt;a href="http://sqlblog.com/files/folders/35240/download.aspx"&gt;Who is Active&lt;/a&gt; stored procedure. A new post will run each day during the month of April, 2011. After April all of these posts will be edited and combined into a single document to become the basis of the Who is Active documentation.&lt;/i&gt;&lt;/p&gt;  &lt;hr&gt;  &lt;p&gt;&lt;b&gt;Pop quiz: &lt;/b&gt;What happens when you promise to write 30 posts on a topic, but you don’t plan properly and lose a bit of steam toward the end?&lt;/p&gt;  &lt;p&gt;Answer: A recap post, a day or two early! Woo hoo!&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;The month started&lt;/b&gt; with a few introductory posts. A &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/01/a-month-of-monitoring-part-1-of-30-a-brief-history-of-monitoring.aspx"&gt;history of monitoring&lt;/a&gt; (from my point of view), some information on Who is Active’s &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/02/who-is-active-design-philosophy-a-month-of-activity-monitoring-part-2-of-30.aspx"&gt;design philosophy&lt;/a&gt;, and a few words on the Who is Active &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/03/who-is-active-the-license-a-month-of-activity-monitoring-part-3-of-30.aspx"&gt;license&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;The key takeaways from these first posts? The monitoring story has been pretty poor for most of SQL Server’s history. It’s better now, but it’s still a lot of work. Who is Active was created to make things more accessible. It’s free, with a few restrictions designed to keep people who make money from monitoring from making money on Who is Active. Anyone else can and should use and enjoy.&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Next I got new users up to speed&lt;/b&gt;. My post on &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/04/installing-who-is-active-a-month-of-activity-monitoring-part-4-of-30.aspx"&gt;installation&lt;/a&gt; covered security considerations, followed by a post on &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/05/less-data-is-more-data-a-month-of-monitoring-part-5-of-30.aspx"&gt;why you may not see as much data as you're used&lt;/a&gt; to when you first start using Who is Active. I continued with a post on the &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/06/who-is-active-options-a-month-of-monitoring-part-6-of-30.aspx"&gt;various options&lt;/a&gt; supported by the procedure (plus a nod to the online help mode) and another post describing the &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/07/who-is-active-default-columns-day-1-a-month-of-activity-monitoring-part-7-of-30.aspx"&gt;default output columns&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;One of the more important posts of the month described how Who is Active treats &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/08/active-request-sleeping-session-a-month-of-activity-monitoring-part-8-of-30.aspx"&gt;active requests and sleeping sessions&lt;/a&gt;. This can be a confusing area for new users, since it's not always obvious what's going on unless you're looking in the right place at the output (the [status] column).&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Once the refresher was finished I began covering &lt;b&gt;some of the basic options exposed by the procedure&lt;/b&gt;. &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/09/deciding-what-not-to-see-a-month-of-activity-monitoring-part-9-of-30.aspx"&gt;Filters &lt;/a&gt;were one of the first things I implemented, so it was a logical place to start (the "not" filters came much later). &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/10/commands-batches-and-the-mysteries-of-text-a-month-of-activity-monitoring-part-10-of-30.aspx"&gt;Seeing the query text&lt;/a&gt; is a key part of the procedure's functionality, and that was next on my list. If you're not sure what the [sql_text] column means, this post will set the record straight.&lt;/p&gt;&lt;p&gt;The ability to see the query text is nice, but so is the ability to get a &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/11/planning-for-success-a-month-of-activity-monitoring-part-11-of-30.aspx"&gt;query plan&lt;/a&gt;--and of course Who is Active supports that too. And since everything a query does is transactional, the procedure allows users to collect information about &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/12/the-almighty-transaction-a-month-of-activity-monitoring-part-12-of-30.aspx"&gt;what those transactions are up to&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;b&gt;The next section of the month was all about query processing&lt;/b&gt;. I started with a couple of background posts: One on &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/13/how-queries-are-processed-a-month-of-activity-monitoring-part-13-of-30.aspx"&gt;how the query processor works&lt;/a&gt; (at a somewhat high level), and another on what blocking &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/14/blocking-blockers-and-other-b-words-a-month-of-activity-monitoring-part-14-of-30.aspx"&gt;&lt;i&gt;really&lt;/i&gt; means&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Who is Active exposes two different modes that help with analysis of real-time waits. My 15th post of the month covered the default--&lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/15/seeing-the-wait-that-matters-most-a-month-of-activity-monitoring-part-15-of-30.aspx"&gt;lightweight--collection mode&lt;/a&gt;. My followup post covered the more extensive &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/16/seeing-all-of-the-waits-a-month-of-activity-monitoring-part-16-of-30.aspx"&gt;full waits collection mode&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;b&gt;Sometimes a query plan and wait information isn't quite enough to diagnose a performance issue&lt;/b&gt;. What if the query plan usually works well, but isn't performing properly only in this specific case? Who is Active &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/17/is-this-normal-a-month-of-activity-monitoring-part-17-of-30.aspx"&gt;has a feature to help you figure that out&lt;/a&gt;. And what if you need &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/18/getting-more-information-a-month-of-activity-monitoring-part-18-of-30.aspx"&gt;a bit more information&lt;/a&gt; on some of the settings that the request is using?&lt;br&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;Mining wait information yields some amazing returns&lt;/b&gt;. One of the additional pieces of information that you can get is the &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/19/why-am-i-blocked-a-month-of-activity-monitoring-part-19-of-30.aspx"&gt;actual name of the object that's causing a block&lt;/a&gt;. Another thing you can see is &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/20/the-node-knows-a-month-of-activity-monitoring-part-20-of-30.aspx"&gt;the exact node within a query plan where a task is currently doing work&lt;/a&gt;. You can (and should!) also use waits to figure out &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/21/analyzing-tempdb-contention-a-month-of-activity-monitoring-part-21-of-30.aspx"&gt;whether &lt;i&gt;tempdb &lt;/i&gt;is properly configured&lt;/a&gt;. There are still more tricks you can play with waits, but they'll have to wait for a future post.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;b&gt;Like wait information, lock data can also be mined.&lt;/b&gt; However, there is so much locks information that the real challenge is rendering it in a human-readable manner. Who is Active does that using a special &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/22/the-key-to-your-locks-a-month-of-activity-monitoring-part-22-of-30.aspx"&gt;custom XML format&lt;/a&gt;. The procedure also helps with another type of blocker analysis, in the form of finding the "&lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/23/leader-of-the-block-a-month-of-activity-monitoring-part-23-of-30.aspx"&gt;lead blocker&lt;/a&gt;."&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Once you've figured out what information you're interested in, why not &lt;b&gt;set up the output so that you can see the information the way you want to see it&lt;/b&gt;? Who is Active helps with this by allowing users to &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/24/the-output-of-your-dreams-a-month-of-activity-monitoring-part-24-of-30.aspx"&gt;dynamically customize output columns and sort order&lt;/a&gt; in a few different ways. And while you could always run Who is Active interactively, that might get a bit dull. &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/25/capturing-the-output-a-month-of-activity-monitoring-part-25-of-30.aspx"&gt;Automated data collection&lt;/a&gt; is a much nicer methodology in many cases.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Most of the numbers shown by Who is Active are cumulative. But oftentimes it's more interesting to &lt;b&gt;compare data between two snapshots&lt;/b&gt;. The procedure can help you do that, using its &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/26/delta-force-a-month-of-activity-monitoring-part-26-of-30.aspx"&gt;delta mode&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;b&gt;What fun would a month of Who is Active be without an official release&lt;/b&gt;? &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/27/who-is-active-v11-00-a-month-of-activity-monitoring-part-27-of-30.aspx"&gt;v11.00 has numerous new features&lt;/a&gt;, several of which were perfected this month thanks to feedback I received on the various posts in the series. It's great to have such enthusiastic users! Some of these new features didn't make it into prior posts, and other existing features are a bit hidden. So I did a writeup covering the &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/28/who-is-active-s-hidden-gems-a-month-of-activity-monitoring-part-28-of-30.aspx"&gt;more important things that you may not have noticed&lt;/a&gt; while working with Who is Active.&lt;br&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;I finished the month with a discussion on &lt;b&gt;security for slightly tougher situations&lt;/b&gt;. I hope that the &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/29/access-for-all-a-month-of-activity-monitoring-part-29-of-30.aspx"&gt;module signing technique&lt;/a&gt; will allow Who is Active to be used in a number of places where security auditing requirements have made things difficult.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;And that's that. A month of activity monitoring with Who is Active. Thank you for reading! Next, this text is going to be edited, expanded in places, and put into a much more comprehensive form. Watch your RSS reader for more information.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Enjoy!&lt;/b&gt; &lt;br&gt;&lt;/p&gt;</description></item><item><title>Access for All! (A Month of Activity Monitoring, Part 29 of 30)</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2011/04/29/access-for-all-a-month-of-activity-monitoring-part-29-of-30.aspx</link><pubDate>Fri, 29 Apr 2011 14:00:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:35300</guid><dc:creator>Adam Machanic</dc:creator><description>&lt;p&gt;&lt;i&gt;This post is part 29 of a 30-part series about the &lt;a href="http://sqlblog.com/files/folders/35240/download.aspx"&gt;Who is Active&lt;/a&gt; stored procedure. A new post will run each day during the month of April, 2011. After April all of these posts will be edited and combined into a single document to become the basis of the Who is Active documentation.&lt;/i&gt;&lt;/p&gt;  &lt;hr&gt;  &lt;p&gt;Early in the month I discussed &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/04/installing-who-is-active-a-month-of-activity-monitoring-part-4-of-30.aspx"&gt;basic security requirements&lt;/a&gt; for Who is Active. I mentioned the VIEW SERVER STATE permission and the fact that I consider it to be “a relatively low barrier to entry.”&lt;/p&gt;  &lt;p&gt;But what if, in your organization, it’s not? &lt;b&gt;Auditing requirements being what they are, you might be required to lock things down&lt;/b&gt;. And granting someone full and unrestricted VIEW SERVER STATE may simply not be an option.&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Enter module signing&lt;/b&gt;. By securing Who is Active (or any other securable, for that matter) via inherited permissions, it’s often possible to get around auditing requirements, as long as the module itself has been reviewed. This is not at all a difficult thing to do, but in my experience most DBAs haven’t played much with signed modules. Today I’ll show you how quick and easy it can be to set things up.&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Start by creating a certificate.&lt;/b&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;USE master       &lt;br&gt;GO&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;CREATE CERTIFICATE WhoIsActive_Permissions       &lt;br&gt;ENCRYPTION BY PASSWORD = '1bigHUGEpwd4WhoIsActive!'        &lt;br&gt;WITH SUBJECT = 'Who is Active',        &lt;br&gt;EXPIRY_DATE = '9999-12-31'        &lt;br&gt;GO&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Once you have a certificate in place, you can create a login from the certificate. The goal is to grant permissions, and to do that you need a principal with which to work; a certificate does not count. A login based on the certificate uses the certificate’s cryptographic thumbprint as its identifier. These logins are sometimes referred to as “loginless logins,” but &lt;a href="http://dataeducation.com/creating-proxies-in-sql-server/"&gt;I refer to them as “proxy logins”&lt;/a&gt; since that’s what they’re used for: proxies for the sake of granting permissions. &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;CREATE LOGIN WhoIsActive_Login       &lt;br&gt;FROM CERTIFICATE WhoIsActive_Permissions        &lt;br&gt;GO&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The login can be granted any permission that can be granted to a normal login. For example, VIEW SERVER STATE:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;GRANT VIEW SERVER STATE       &lt;br&gt;TO WhoIsActive_Login        &lt;br&gt;GO&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Once the permission has been granted, the certificate can be used to sign the module—in this case, Who is Active. When the procedure is executed, a check will be made to find associated signatures. The thumbprint of the certificates and/or keys used to sign the module will be checked for associated logins, and any permissions granted to the logins will be available within the scope of the module—meaning that the caller will temporarily gain access.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;ADD SIGNATURE TO sp_WhoIsActive       &lt;br&gt;BY CERTIFICATE WhoIsActive_Permissions        &lt;br&gt;WITH PASSWORD = '1bigHUGEpwd4WhoIsActive!'        &lt;br&gt;GO&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;b&gt;Getting to this step will be enough to allow anyone with EXECUTE permission on Who is Active to exercise most of its functionality&lt;/b&gt;. There are a couple of notes and caveats: First of all, every time you ALTER the procedure (such as when upgrading to a new version), the signature will be dropped and the procedure will have to be re-signed. You won’t have to create the certificate or the login again; you’ll just have to re-run that final statement. Second, you’ll only be able to use &lt;i&gt;most&lt;/i&gt; of the functionality. Certain features, such as blocked object resolution mode, won’t operate properly, depending on whether the caller has access to the database in which the block is occurring. This may or may not be a problem—it depends on your environment and what users need to see—and Who is Active itself won’t throw an exception. An error message will be returned somewhere in the results, depending on what the user has tried to do. &lt;/p&gt;  &lt;p&gt;If you would like to grant database-level permissions based on the certificate login so as to avoid these errors, that’s doable to. Just do something like:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;USE AdventureWorks       &lt;br&gt;GO&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;CREATE USER WhoIsActive_User       &lt;br&gt;FOR LOGIN WhoIsActive_Login        &lt;br&gt;GO&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;EXEC sp_addrolemember        &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'db_datareader',        &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'whoisactive_user'        &lt;br&gt;GO&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This will allow Who is Active to figure out what the various blocked or locked object names are. Since the login is just a proxy no one can actually log in and get direct access to read the data, so this isn’t something I consider to be a security risk. However, keep in mind that if anyone has the password for the certificate and sufficient privileges in &lt;i&gt;master&lt;/i&gt;, a new module could be created and signed. Keep the password secure, and make sure to carefully audit to catch any infractions before they become a risk.&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Security policy should never be a reason to limit your monitoring choices&lt;/b&gt;. Module signing is a powerful tool for Who is Active in addition to many other applications. I highly recommend studying it in detail in order to enhance your ability to provide high-quality, totally flexible, and completely secure solutions.&lt;/p&gt;</description></item><item><title>Who is Active's Hidden Gems (A Month of Activity Monitoring, Part 28 of 30)</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2011/04/28/who-is-active-s-hidden-gems-a-month-of-activity-monitoring-part-28-of-30.aspx</link><pubDate>Thu, 28 Apr 2011 14:00:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:35114</guid><dc:creator>Adam Machanic</dc:creator><description>&lt;p&gt;&lt;i&gt;This post is part 28 of a 30-part series about the &lt;a href="http://sqlblog.com/files/folders/35240/download.aspx"&gt;Who is Active&lt;/a&gt; stored procedure. A new post will run each day during the month of April, 2011. After April all of these posts will be edited and combined into a single document to become the basis of the Who is Active documentation.&lt;/i&gt;&lt;/p&gt;  &lt;hr&gt;  &lt;p&gt;&lt;b&gt;Over the past month this series has covered a lot of ground.&lt;/b&gt; After writing almost 30 blog posts on the stored procedure it’s interesting to look back and see the fact that it’s gotten much bigger and more complex than I realized. Kind of like watching a plant grow, you don’t notice the day-to-day changes until one day you go to water it and see that it’s taken over your entire garden.&lt;/p&gt;  &lt;p&gt;A few things that I’ve added along the way have been especially useful, but there hasn’t been a good place to mention them thus far in the series. With just three posts left for the month, now is the time.&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;u&gt;Always Show Blockers&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;In &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/09/deciding-what-not-to-see-a-month-of-activity-monitoring-part-9-of-30.aspx"&gt;a post earlier this month&lt;/a&gt; I talked about filters. Filters let you decide exactly what you want to see, and what you not don’t want to see (“not” filters). But sometimes you have no choice: if you’re filtering so that you only see session 123, and it’s being blocked by session 456, you’ll also see information about session 456. The idea is that you should &lt;i&gt;always&lt;/i&gt; get enough context to fully evaluate the problem at hand. Even if it means that you see more information than you were intending to see the first time around. You probably would have asked for 456 next anyway.&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;u&gt;“RUNNABLE” Waits&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;In &lt;i&gt;@get_task_info = 2&lt;/i&gt; mode, you may see waits called “RUNNABLE.” This could strike you as an oddity, given that &lt;i&gt;there is no such wait type&lt;/i&gt; in SQL Server. I wanted to show &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/13/how-queries-are-processed-a-month-of-activity-monitoring-part-13-of-30.aspx"&gt;tasks on the runnable queue&lt;/a&gt;, and making up a fake wait type seemed like a reasonable way of accomplishing the task. In practice, it has worked extremely well—I’ve used this feature countless times to help understand scheduler contention on a SQL Server instance.&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;u&gt;Accurate CPU Time Deltas&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;CPU time is a tricky metric. It gets handled by Who is Active’s &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/26/delta-force-a-month-of-activity-monitoring-part-26-of-30.aspx"&gt;delta mode&lt;/a&gt;, and has for several versions. But historically, never very well. The data &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/02/who-is-active-design-philosophy-a-month-of-activity-monitoring-part-2-of-30.aspx"&gt;simply isn’t represented in an easily-obtainable fashion&lt;/a&gt; in the core DMVs. Recently I decided to dig deeper into this problem and discovered that I could get better numbers from some of the thread-specific DMVs. They’re cumulative numbers, based on the lifetime of the entire thread—not too good for the usual Who is Active output. But for snapshot and delta purposes, just about perfect. Meaning that in v11.00 of Who is Active, you can see the [CPU] column show a value of 0, while the [CPU_delta] column shows a value in the thousands. It’s not a bug. It’s a feature. (It really is!)&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;u&gt;Text Query Plans and the XML Demon&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;SQL Server 2005 introduced query plans as XML. Management Studio knew how to render these plans graphically. And we were able to pull the plans from DMVs. Life was great. Except, perhaps, when you actually wanted to view one of these plans, and you had to save the thing out to a .SQLPLAN file, close the file, then re-open it. That’s about three steps too many for my taste, so I was overjoyed when the Management Studio team decided to wire things up the right way in SQL Server 2008. Click on a showplan XML document, see a graphical plan. Simple as that. &lt;/p&gt;  &lt;p&gt;Unfortunately, the XML data type has its own issues, including one particularly nasty arbitrary limitation that has to do with nesting depth. The idea is to make sure that XML indexes don’t crash and burn too often (not a big concern for me, given that I’ve never seen one used in a production environment—but I digress). The problem is that query plans are heavily nested. And to get that nice graphical plan workflow, SSMS needs the plan rendered as XML. &lt;/p&gt;  &lt;p&gt;In prior versions of Who is Active I gave up and returned either an error or a NULL. But in v11.00 I decided to make things a bit better. If the nesting issue occurs, Who is Active will now return the plan as XML encapsulated in some other XML in a text format, along with instructions on how to view the plan. This won’t give you a nice one-click experience, but it will give you the ability to use Who is Active to see some of the bigger plans that are causing performance issues.&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;u&gt;Service Broker Needs Love Too&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;One of the most interesting features of Service Broker is activation. But a vexing design choice on behalf of the Service Broker team was to make activation procedures launch as system sessions. This means, among other things, that prior versions of Who is Active filtered them right out of the default view. To see them you’d have to enable &lt;i&gt;@show_system_spids&lt;/i&gt;. And then you’d have to ignore all of the other system stuff. And you’d get woefully bad time information (no, the activation process hasn’t been running for 25 days; that’s the last time you restarted the SQL Server instance). In Who is Active v11.00 this has been fixed. Service Broker activation processes are now displayed by default along with other user activity. And I found a way to fix the timing issue, thanks to some advice on Twitter from Remus Rusanu, one of the guys who originally worked on Service Broker. So if you’re using activation and monitoring with Who is Active, life is good.&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;u&gt;Homework&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;The homework section of this series is officially closed. Your assignment is to go enjoy the rest of your day.&lt;/p&gt;</description></item><item><title>Who is Active v11.00 (A Month of Activity Monitoring, Part 27 of 30)</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2011/04/27/who-is-active-v11-00-a-month-of-activity-monitoring-part-27-of-30.aspx</link><pubDate>Wed, 27 Apr 2011 14:00:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:35113</guid><dc:creator>Adam Machanic</dc:creator><description>&lt;p&gt;&lt;i&gt;This post is part 27 of a 30-part series about the &lt;a href="http://sqlblog.com/files/folders/35240/download.aspx"&gt;Who is Active&lt;/a&gt; stored procedure. A new post will run each day during the month of April, 2011. After April all of these posts will be edited and combined into a single document to become the basis of the Who is Active documentation.&lt;/i&gt;&lt;/p&gt;  &lt;hr&gt;  &lt;p&gt;&lt;b&gt;Thanks to your feedback over the past month, I’ve managed to get a lot of work done on the next version of Who is Active.&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;So much work, in fact, that I’ve finished a new major release.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;a href="http://sqlblog.com/files/folders/35240/download.aspx"&gt;&lt;b&gt;Click here to download Who is Active v11.00&lt;/b&gt;&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;There are numerous enhancements in this release. In no particular order:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;CPU deltas use-time thread-based metrics for more accurate data (use both @delta_interval and @get_task_info = 2)&lt;/li&gt;    &lt;li&gt;command_type information added to [additional_info] column for active requests &lt;/li&gt;    &lt;li&gt;Modified elapsed time logic to retrieve more accurate timing information for active system SPIDs&lt;/li&gt;    &lt;li&gt;SQL Agent job info (job name and step name) is now included in the additional_info column (use @get_additional_info = 1) &lt;/li&gt;    &lt;li&gt;If there is a lock wait, information about the blocked object (name, schema name, and ID) is now included in the additional_info column (use both @get_additional_info = 1 and @get_task_info = 2) &lt;/li&gt;    &lt;li&gt;Service Broker activated tasks are now shown by default, without using @show_system_spids mode. The program_name column contains the queue_id and database_id associated with the activation procedure&lt;/li&gt;    &lt;li&gt;Various numeric columns, including reads, writes, cpu, etc, have been made nullable. These will occasionally return NULL, on extremely active systems where the DMVs return data more slowly than queries start and complete &lt;/li&gt;    &lt;li&gt;Query plans that cannot be rendered due to XML type limitations are now returned in an encapsulated format, with instructions, rather than sending back an error &lt;/li&gt;    &lt;li&gt;Added wait information for OLEDB/linked server waits &lt;/li&gt;    &lt;li&gt;Wait collection will now "downgrade" to get_task_info = 1 style data if no other information is available in get_task_info = 2 mode &lt;/li&gt;    &lt;li&gt;Added header information to online help &lt;/li&gt;    &lt;li&gt;Added a login_time column to the output &lt;/li&gt;    &lt;li&gt;The duration for sleeping sessions is now the sleep time, rather than the time since login&lt;/li&gt;    &lt;li&gt;Fixed various bugs&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I’ve written about several of these things over the past month, and there are a couple of posts left for the remainder of the month, so I won't elaborate here. &lt;/p&gt;  &lt;p&gt;Thank you, thank you, and thank you again to everyone who has taken the time to give me feedback and/or report bugs! Who is Active would not be what it is without you! &lt;/p&gt;&lt;p&gt;&lt;b&gt;I would especially like to thank Paul White. &lt;/b&gt;Paul has acted as my unofficial "lead QA engineer" for the past few versions. He's found some very interesting bugs in my code, in addition to pointing out some quirks in the DMVs that I wasn’t handling properly. Thanks, Paul, for the great job you’ve done!&lt;/p&gt;  &lt;p&gt;&lt;b&gt;One other thing I would like to point out is an addition to the header: a donation link&lt;/b&gt;. Several people recently have asked me how to donate, and I didn’t have a good answer. Now, I do.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;a href="http://tinyurl.com/WhoIsActiveDonate"&gt;&lt;b&gt;Use this link to support the Who is Active project!&lt;/b&gt;&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;While I feel strange asking for money, the truth is that I’ve invested well over a thousand hours in the stored procedure, documentation, and support (I respond to EVERY e-mail I receive from Who is Active users). If you’ve been able to improve your day-to-day performance thanks to Who is Active, it would be great if you—or even better, your employer—could help support my work on the project. &lt;b&gt;I’ve listed a recommended donation of $40 per installed instance, but please donate however much you feel Who is Active is worth to you and/or your organization.&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;Thanks again, and enjoy!&lt;/p&gt;</description></item><item><title>Delta Force (A Month of Activity Monitoring, Part 26 of 30)</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2011/04/26/delta-force-a-month-of-activity-monitoring-part-26-of-30.aspx</link><pubDate>Tue, 26 Apr 2011 14:00:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:35112</guid><dc:creator>Adam Machanic</dc:creator><description>&lt;p&gt;&lt;i&gt;This post is part 26 of a 30-part series about the &lt;a href="http://sqlblog.com/files/folders/35046/download.aspx"&gt;Who is Active&lt;/a&gt; stored procedure. A new post will run each day during the month of April, 2011. After April all of these posts will be edited and combined into a single document to become the basis of the Who is Active documentation.&lt;/i&gt;&lt;/p&gt;  &lt;hr&gt;  &lt;p&gt;The CPU is pegged. Your hard disks are fried. Memory consumption is through the roof. &lt;b&gt;Who is to blame?!?&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;Well that’s easy. Blame the session with the most CPU consumption. Blame the session doing the most I/O operations. Ask Who is Active what’s going on—it’ll tell you...&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/adam_machanic/F26_01_cpu_74325373.jpg"&gt;&lt;img src="http://sqlblog.com/blogs/adam_machanic/F26_01_cpu_thumb_7A0CF70C.jpg" style="background-image:none;border:0px none;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;" title="F26_01_cpu" alt="F26_01_cpu" border="0" height="84" width="365"&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&lt;i&gt;Clearly&lt;/i&gt; session 52 is the problem here. It’s consumed over 2,000,000 milliseconds of CPU time. Session 53, on the other hand, has consumed a paltry five seconds. No brainer, right?&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Except that it’s not&lt;/b&gt;.&lt;/p&gt;  &lt;p&gt;Session 52? It’s in a wait state. (WAITFOR, to be exact.) Not consuming any CPU time at all at the time I ran Who is Active. Session 53? Using plenty. So why the discrepancy? Does Who is Active have a major bug? &lt;/p&gt;  &lt;p&gt;The fact is—and this will be obvious to a lot of you, so forgive me—most of the metrics reported by Who is Active are &lt;i&gt;cumulative&lt;/i&gt;. They’re totals from the entire session, or the entire lifetime of the request (depending on what’s going on). In the case of session 52 in the image above, that much CPU time was consumed over a five-minute period &lt;i&gt;prior&lt;/i&gt; to the point in time when I ran Who is Active. Session 53, on the other hand, is &lt;i&gt;currently&lt;/i&gt; consuming CPU time. But how do I figure that out?&lt;/p&gt;  &lt;p&gt;&lt;b&gt;The answer: delta mode.&lt;/b&gt; This feature is something for which you can thank Jimmy May, who kept telling me about his “SQL Deltoids” script that he’d written back in the bad old days of SQL Server 2000. “If only there were a way to apply that script to the SQL Server 2005 DMVs,” he lamented one day. So I added the functionality into Who is Active. It’s quite simple, and surprisingly effective.&lt;/p&gt;  &lt;p&gt;To use delta mode, simply invoke Who is Active’s &lt;i&gt;@delta_interval&lt;/i&gt; option. Setting an interval will cause the procedure to execute its main logic branch, then wait the specified amount of time—a number of seconds between 1 and 255—before running the same main logic branch again. All of the numeric values that changed during that period will be compared, and the changed numbers will be output in a series of columns named with &lt;i&gt;_delta&lt;/i&gt; at the end. &lt;/p&gt;  &lt;p&gt;For example, here are the same two sessions as above, viewed in delta mode:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;EXEC sp_WhoIsActive       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @delta_interval = 5&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/adam_machanic/F26_02_delta_79349122.jpg"&gt;&lt;img src="http://sqlblog.com/blogs/adam_machanic/F26_02_delta_thumb_062E7134.jpg" style="background-image:none;border:0px none;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;" title="F26_02_delta" alt="F26_02_delta" border="0" height="83" width="463"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;During the five-second delta interval, session 52 consumed no CPU time. Session 53, on the other hand, consumed over 5,000 milliseconds of time. If the CPU is pegged, 52 is no longer contributing—53 is the session of interest.&lt;/p&gt;  &lt;p&gt;Enabling delta mode will add some or all of the following columns to the output, depending on what other options have been set:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;physical_io_delta&lt;/li&gt;    &lt;li&gt;reads_delta&lt;/li&gt;    &lt;li&gt;physical_reads_delta&lt;/li&gt;    &lt;li&gt;writes_delta&lt;/li&gt;    &lt;li&gt;tempdb_allocations_delta&lt;/li&gt;    &lt;li&gt;tempdb_current_delta&lt;/li&gt;    &lt;li&gt;CPU_delta&lt;/li&gt;    &lt;li&gt;context_switches_delta&lt;/li&gt;    &lt;li&gt;used_memory_delta&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;By leveraging these delta columns in conjunction with the &lt;i&gt;@sort_order&lt;/i&gt; option, it’s easy to quickly see which sessions are &lt;i&gt;currently&lt;/i&gt; consuming your valuable server resources—which is generally more interesting than seeing which sessions may have been consuming resources but are now waiting or sleeping.&lt;/p&gt;&lt;p&gt;Note: The various sessions and requests you'll see in delta mode pertain to the information captured after the wait interval. Information about requests that were running as of the first collection but are not running as of the second is discarded. New requests that started after the first collection will be shown, but with delta values of NULL. Locks, transactions, and other optional information, will also be captured only for the second collection, since no delta calculation is possible for those metrics (at least, not yet).&lt;br&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;u&gt;Homework&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;Delta mode, in its current form, is only really useful if you have requests that last longer than a second (at minimum—I usually do five or ten-second intervals). What kind of workload do you see on your servers? Is delta mode as it exists today something that you’re making use of (or that you’ll start making use of, now that I’ve written a post about it)?&lt;/p&gt;</description></item><item><title>Capturing the Output (A Month of Activity Monitoring, Part 25 of 30)</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2011/04/25/capturing-the-output-a-month-of-activity-monitoring-part-25-of-30.aspx</link><pubDate>Mon, 25 Apr 2011 14:00:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:35111</guid><dc:creator>Adam Machanic</dc:creator><description>&lt;p&gt;&lt;i&gt;This post is part 25 of a 30-part series about the &lt;a href="http://sqlblog.com/files/folders/35240/download.aspx"&gt;Who is Active&lt;/a&gt; stored procedure. A new post will run each day during the month of April, 2011. After April all of these posts will be edited and combined into a single document to become the basis of the Who is Active documentation.&lt;/i&gt;&lt;/p&gt;  &lt;hr&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/24/the-output-of-your-dreams-a-month-of-activity-monitoring-part-24-of-30.aspx"&gt;Yesterday’s post&lt;/a&gt; was about configuring the output based on what &lt;i&gt;you&lt;/i&gt; want to see. &lt;b&gt;Today’s post is about taking that perfect output and persisting it.&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;There are many reasons that you might like to store the results of a Who is Active call to a table. Some of the real use cases that I’ve been told about by Who is Active users include:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Scheduled monitoring. Capturing the results of Who is Active calls in 5 or 10 minute intervals to see what’s happening on the database server throughout the day (or night)&lt;/li&gt;    &lt;li&gt;Using it as part of a build process, to verify that the correct things are happening in the correct order at the correct times&lt;/li&gt;    &lt;li&gt;Using it as part of an exception handling system that automatically calls Who is Active every time an error occurs, to snapshot the current state of the database instance&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;And there are various other use cases in addition to these. The point is that there are a number of reasons that you might want to capture the output. &lt;/p&gt;  &lt;p&gt;&lt;b&gt;Unfortunately, it’s not as simple a task as you might think.&lt;/b&gt; The first time I tried to make it work, I did something like:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;CREATE TABLE #output       &lt;br&gt;(        &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...        &lt;br&gt;)&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;INSERT #output       &lt;br&gt;EXEC sp_WhoIsActive&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This approach failed miserably. If you try it, as I did, you’ll see the following error message:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;Msg 8164, Level 16, State 1, Procedure sp_WhoIsActive, Line 3086       &lt;br&gt;An INSERT EXEC statement cannot be nested.&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Who is Active uses a number of INSERT EXEC statements, and they cannot be easily changed or removed, so for a while it seemed like all was lost. After a bit of brainstorming, however, I realized that I could simply build yet another INSERT EXEC into Who is Active—one that will insert into a table of your choice.&lt;/p&gt;  &lt;p&gt;Of course, first you need a table. And if you’ve been reading this series you’re no doubt aware that the output shape returned by Who is Active is extremely dynamic in nature, and depends on which parameters are being used. So the first option I added was&lt;b&gt; a method by which you can get the output schema. &lt;/b&gt;Two parameters are involved: If &lt;i&gt;@return_schema&lt;/i&gt; is set to &lt;b&gt;1&lt;/b&gt;, the schema shape will be returned in an &lt;i&gt;OUTPUT&lt;/i&gt; parameter called &lt;i&gt;@schema&lt;/i&gt;. This is best shown by way of example:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;DECLARE @s VARCHAR(MAX)&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;EXEC sp_WhoIsActive       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @output_column_list = '[temp%]',        &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @return_schema = 1,        &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @schema = @s OUTPUT&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;SELECT @s&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The idea is that you set up your Who is Active call with all of the options you’d like, then bolt on the &lt;i&gt;@return_schema&lt;/i&gt; and &lt;i&gt;@schema&lt;/i&gt; parameters. Here the column list is being restricted to only those columns having to do with &lt;i&gt;tempdb&lt;/i&gt;. If you run this code, the &lt;i&gt;SELECT&lt;/i&gt; will return the following result:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;CREATE TABLE &amp;lt;table_name&amp;gt; ( [tempdb_allocations] varchar(30) NULL,[tempdb_current] varchar(30) NULL)&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This result can be modified by replacing the “&amp;lt;table_name&amp;gt;” placeholder with the name of the table you actually want to persist the results to. Of course this can be done either manually or automatically—after the call to Who is Active, the text is sitting in a variable, so a simple call to &lt;i&gt;REPLACE&lt;/i&gt; is all that’s needed. That call could even be followed up by a call to execute the result and create the table...&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;DECLARE @s VARCHAR(MAX)&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;EXEC sp_WhoIsActive       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @output_column_list = '[temp%]',        &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @return_schema = 1,        &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @schema = @s OUTPUT&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;SET @s = REPLACE(@s, '&amp;lt;table_name&amp;gt;', 'tempdb.dbo.monitoring_output')&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;EXEC(@s)&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;b&gt;Of course now you probably want to put something into the table&lt;/b&gt;. Crazy! To do this, drop the &lt;i&gt;@return_schema&lt;/i&gt; and &lt;i&gt;@schema&lt;/i&gt; parameters and replace them with &lt;i&gt;@destination_table&lt;/i&gt;—the name of the table into which the results should be inserted:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;EXEC sp_WhoIsActive     &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @output_column_list = '[temp%]',      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @destination_table = 'tempdb.dbo.monitoring_output'&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Now the results of the call will be inserted into the destination table. Just remember that every time you change the Who is Active options, you’ll have to re-acquire the output shape. Even a small change, such as adding an additional column to the output list, will result in a catastrophic error.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;EXEC sp_WhoIsActive       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @output_column_list = '[session_id][temp%]',        &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @destination_table = 'tempdb.dbo.monitoring_output'&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;Msg 213, Level 16, State 1, Line 1       &lt;br&gt;Column name or number of supplied values does not match table definition.&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;b&gt;How far you take this feature depends on how creative you are&lt;/b&gt;. Some of you have come up with elaborate schemes, but I generally keep it simple. Something that I like to do is to set up a short semi-automated process by using Management Studio’s &lt;i&gt;GO [N]&lt;/i&gt; option. I use this when I’m doing intense debugging, and will do something like:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;DECLARE @s VARCHAR(MAX)&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;EXEC sp_WhoIsActive       &lt;br&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @format_output = 0,       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @return_schema = 1,        &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @schema = @s OUTPUT&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;SET @s = REPLACE(@s, '&amp;lt;table_name&amp;gt;', 'tempdb.dbo.quick_debug')&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;EXEC(@s)       &lt;br&gt;GO&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;EXEC sp_WhoIsActive       &lt;br&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @format_output = 0,&lt;/font&gt;        &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @destination_table = 'tempdb.dbo.quick_debug'&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;WAITFOR DELAY '00:00:05'       &lt;br&gt;GO 60&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This will first create a table in &lt;i&gt;tempdb&lt;/i&gt;, after which it will collect the results every five seconds for a five-minute period. I set &lt;i&gt;@format_output&lt;/i&gt; to &lt;b&gt;0&lt;/b&gt; in order to get rid of the text formatting so that I can more easily work with the numeric data. &lt;b&gt;The results can be correlated to performance counters or other external information&lt;/b&gt; using the [collection_time] column, which was added to Who is Active specifically to support automated data collection.&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;u&gt;Homework&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;Share your experiences with Who is Active’s data collection feature. How are you using it? Have you hit any problems or roadblocks? Any awesome success stories? A few sentences will be great, and more is fine if you’re in the mood to tell a story.&lt;/p&gt;</description></item><item><title>The Output of Your Dreams (A Month of Activity Monitoring, Part 24 of 30)</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2011/04/24/the-output-of-your-dreams-a-month-of-activity-monitoring-part-24-of-30.aspx</link><pubDate>Sun, 24 Apr 2011 14:00:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:35110</guid><dc:creator>Adam Machanic</dc:creator><description>&lt;p&gt;&lt;i&gt;This post is part 24 of a 30-part series about the &lt;a href="http://sqlblog.com/files/folders/35240/download.aspx"&gt;Who is Active&lt;/a&gt; stored procedure. A new post will run each day during the month of April, 2011. After April all of these posts will be edited and combined into a single document to become the basis of the Who is Active documentation.&lt;/i&gt;&lt;/p&gt;  &lt;hr&gt;  &lt;p&gt;&lt;b&gt;Early in the process of creating Who is Active it became clear that there was no way everyone was going to agree.&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;With each release I received requests to move some column so that it would show up on the lefthand side, or to change the sort order, or to make some other modification that someone felt was necessary to help them more easily digest the data. The problem: it was impossible to accommodate all of these requests. So I decided to go with a self-service model.&lt;/p&gt;  &lt;p&gt;In order to allow users to dynamically customize the output (without touching any code), the stored procedure exposes three options: &lt;i&gt;@output_column_list&lt;/i&gt;, &lt;i&gt;@sort_order&lt;/i&gt;, and &lt;i&gt;@format_output&lt;/i&gt;. Each of these is discussed in the following sections.&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;i&gt;@output_column_list&lt;/i&gt;&lt;/b&gt; controls not only whether or not certain columns will be shown in the output, but also the order in which the columns are displayed. The correct argument is a list of bracket-delimited column names (or partial names with wildcards). Delimiters are not necessary (use whatever delimiter you like, or none at all; they’re ignored). The key to successfully using this option is to remember that inclusion of columns in the output is additive: many columns (such as [additional_info]) are only added to the output if both the correct options are enabled for the stored procedure and the columns are included in the column list. If you start modifying the list and don’t take this into account, you may not see the columns you’re expecting when you go back later and start changing options. To keep things flexible, make sure to use wildcard columns, especially a generic wildcard (&lt;i&gt;[%]&lt;/i&gt;) at the end.&lt;/p&gt;  &lt;p&gt;Using the column list can be as simple as specifying the exact columns you’re interested in:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;EXEC sp_WhoIsActive       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @output_column_list = '[tempdb_allocations][tempdb_current]'&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Notice that no delimiter is used here. Again, any extraneous text aside from the column specifiers is ignored, so the following call is equivalent:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;EXEC sp_WhoIsActive       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @output_column_list = 'this[tempdb_allocations]is[tempdb_current]ignored'&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Easier than specifying exact column names is to use wildcards that match the pattern of the columns you’re interested in:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;EXEC sp_WhoIsActive       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @output_column_list = '[tempdb%]'&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;All three of these calls will yield the same output, similar to the following:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/adam_machanic/F24_01_column_list_0638D459.jpg"&gt;&lt;img src="http://sqlblog.com/blogs/adam_machanic/F24_01_column_list_thumb_654561B1.jpg" style="background-image:none;border:0px none;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;" title="F24_01_column_list" alt="F24_01_column_list" border="0" height="59" width="283"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Of course, this will return &lt;i&gt;only&lt;/i&gt; these two columns. Generally I’ll use the column list feature just to move things around so that I don’t have to do as much scrolling, and in those cases I almost always want everything else, too. That’s where the generic wildcard comes into play:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;EXEC sp_WhoIsActive       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @output_column_list = '[tempdb%][%]'&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/adam_machanic/F24_02_all_cols_5DB9F244.jpg"&gt;&lt;img src="http://sqlblog.com/blogs/adam_machanic/F24_02_all_cols_thumb_71D30ECD.jpg" style="background-image:none;border:0px none;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;" title="F24_02_all_cols" alt="F24_02_all_cols" border="0" height="59" width="638"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Now the &lt;i&gt;tempdb&lt;/i&gt;-specific columns appear on the lefthand side, and all of the other columns follow, in a default order.&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;The next option we’ll cover is &lt;i&gt;@sort_order&lt;/i&gt;&lt;/b&gt;. This option controls the order of the rows output by the stored procedure. Like &lt;i&gt;@output_column_list&lt;/i&gt;, the input is a list of bracket-delimited column names. In this case, wildcards are not supported, but the keywords &lt;i&gt;ASC&lt;/i&gt;[ENDING] and &lt;i&gt;DESC&lt;/i&gt;[ENDING] are supported after the column name.&lt;/p&gt;  &lt;p&gt;The following call returns data sorted by [login_name] ascending (ascending is default, so the keyword is optional), with ties broken by [session_id] descending:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;EXEC sp_WhoIsActive       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @sort_order = '[login_name][session_id] DESC'&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;As before, delimiters are optional and are ignored. Please note that the current betas of Who is Active have bug where multi-column sorts like this one are not properly honored. That issue will be fixed in the next version of Who is Active. &lt;/p&gt;  &lt;p&gt;Sorting is especially useful when doing any kind of comparison of the various requests currently running. I use it extensively in block leader mode ([blocked_session_count] DESC), and it is quite handy in delta mode—which will be covered in a post in a few days.&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;The final option this post will cover is&lt;i&gt; @format_output&lt;/i&gt;.&lt;/b&gt; This one is based on the fact that Who is Active is designed to leverage SSMS as a “graphical user interface” of sorts. Query text is sent back in an XML format, numbers are formatted as right-justified strings, and elapsed time is formatted in the more easily-digestible [dd hh:mm:ss.mss] form. &lt;/p&gt;  &lt;p&gt;If you’ve been using Who is Active for a while you’ve probably noticed the right-justified numbers:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/adam_machanic/F24_03_right_justified_7819E55B.jpg"&gt;&lt;img src="http://sqlblog.com/blogs/adam_machanic/F24_03_right_justified_thumb_50736931.jpg" style="background-image:none;border:0px none;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;" title="F24_03_right_justified" alt="F24_03_right_justified" border="0" height="69" width="308"&gt;&lt;/a&gt;&lt;/p&gt;      &lt;p&gt;This format was suggested fairly early on by Aaron Bertrand, and is one of my favorite things about the stored procedure. It makes it much easier to pick out bigger numbers when you’re looking at a large set of data. By default, SSMS uses a non-fixed width font for grid results, so the default argument to &lt;i&gt;@format_output, &lt;/i&gt;&lt;b&gt;1&lt;/b&gt;, takes this into consideration. But some people—like Aaron Bertrand—change the SSMS settings and use a fixed width font instead. If you’re one of these people you can use an argument of &lt;b&gt;2&lt;/b&gt; to get nicely-formatted numbers. If you don’t change the argument you might notice that the numbers don’t seem to properly line up when you’re working with a set of data containing numbers of greatly differing size.&lt;/p&gt;  &lt;p&gt;Still other people don’t like the right-justified numbers or are doing collection to a table (see tomorrow's post), and so formatting can be completely disabled by using an argument of &lt;b&gt;0&lt;/b&gt;. It’s up to you...&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;u&gt;Homework&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;Today’s homework is to enjoy your Sunday. You’re a busy DBA; you’ve earned a break. Get outside and off of the computer!&lt;/p&gt;</description></item><item><title>Leader of the Block (A Month of Activity Monitoring, Part 23 of 30)</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2011/04/23/leader-of-the-block-a-month-of-activity-monitoring-part-23-of-30.aspx</link><pubDate>Sat, 23 Apr 2011 14:00:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:35109</guid><dc:creator>Adam Machanic</dc:creator><description>&lt;p&gt;&lt;i&gt;This post is part 23 of a 30-part series about the &lt;a href="http://sqlblog.com/files/folders/35240/download.aspx"&gt;Who is Active&lt;/a&gt; stored procedure. A new post will run each day during the month of April, 2011. After April all of these posts will be edited and combined into a single document to become the basis of the Who is Active documentation.&lt;/i&gt;&lt;/p&gt;  &lt;hr&gt;  &lt;p&gt;&lt;b&gt;Oftentimes blocking situations are a bit more complex than one session blocking some other request&lt;/b&gt;. In busy systems &lt;i&gt;blocking chains&lt;/i&gt; can build up that include dozens or even hundreds of requests, all waiting on one another. And all are waiting as a result of one top-level blocker: the &lt;i&gt;block leader&lt;/i&gt;. In many cases fixing the blocking problem means fixing whatever it is that the block leader is doing, so identifying it quickly is a key part of debugging blocking situations.&lt;/p&gt;  &lt;p&gt;Finding the block leader is a fairly simple process once you realize that &lt;b&gt;blocking is effectively a hierarchy&lt;/b&gt;. The process involves starting with all of the requests that aren’t blocked and walking down the blocking chain until the leaf level is reached—blockees that lack any more downstream blockees. At each level, a number is recorded to figure out the blocking depth. As an added benefit, a second pass can be made to reverse the number at the end of the process—this shows the total number of downstream blockees for each blocker.&lt;/p&gt;  &lt;p&gt;While this is relatively easy to implement using a Common Table Expression, &lt;b&gt;it’s certainly not something that users should have to reinvent each time it’s needed&lt;/b&gt;. So Who is Active exposes an option, &lt;i&gt;@find_block_leaders&lt;/i&gt;, that does the work for you. This option adds a new column to the output, called [blocked_session_count], which reflects the total blockee count. Higher numbers mean more sessions blocked downstream; the sessions with the highest numbers are your block leaders, and these are the ones you want to focus on.&lt;/p&gt;  &lt;p&gt;To see this in a bit more detail, run the following batch in four sessions:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;USE AdventureWorks       &lt;br&gt;GO&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;BEGIN TRAN       &lt;br&gt;GO&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;UPDATE TOP(10) Sales.SalesOrderDetail       &lt;br&gt;SET OrderQty += 7;        &lt;br&gt;GO&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Assuming that nothing else is running, the first session will complete. The other three will block. Who is Active reports this, of course, even in its default mode:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/adam_machanic/F23_01_blocked_7031F8F4.jpg"&gt;&lt;img src="http://sqlblog.com/blogs/adam_machanic/F23_01_blocked_thumb_6EED6015.jpg" style="background-image:none;border:0px none;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;" title="F23_01_blocked" alt="F23_01_blocked" border="0" height="115" width="708"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The initial update was run on session 53, which is blocking session 54. Both 55 and 56 are reported as blocked by 54, although in reality they’re being blocked indirectly by 53. This case, while more complex than most of the blocking examples used in this series, is still simpler than many of the things seen on average production systems. None the less, it’s enough to show the power of the Who is Active option that this post is about...&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;EXEC sp_WhoIsActive     &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @find_block_leaders = 1&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/adam_machanic/F23_02_leaders_592377B8.jpg"&gt;&lt;img src="http://sqlblog.com/blogs/adam_machanic/F23_02_leaders_thumb_38300511.jpg" style="background-image:none;border:0px none;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;" title="F23_02_leaders" alt="F23_02_leaders" border="0" height="116" width="869"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The [blocked_session_count] clearly shows which session is causing the issue in this case: 53 has three downstream blockees, whereas 54 has only two, and the other two sessions have none. &lt;/p&gt;  &lt;p&gt;In this case, because I happened to run the batches in the correct order, the data is returned by default with the block leader sorted on top. That may or may not always be the case in a real system, but it’s quite a useful thing when there are numerous active requests and you want the most important ones right at the top. To accomplish that, use the output ordering feature—which will be covered in detail in tomorrow’s post.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;EXEC sp_WhoIsActive       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @find_block_leaders = 1,        &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @sort_order = '[blocked_session_count] DESC'&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;u&gt;Homework&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;Today’s “homework” is a question for you to consider about the behavior of Who is Active with regard to sleeping sessions: Today the [start_time] and [dd hh:mm:ss.mss] columns, for sleeping sessions, correspond to the login time for the session. But recently I’ve been thinking that it might make more sense to instead show the amount of time since the last request completed—the amount of time that the session has been sleeping. This seems to me to be more useful information and more in line with the goal of the stored procedure.&lt;/p&gt;  &lt;p&gt;Which would you rather see, and why? I would appreciate any input and will carefully consider it. This would be a fairly major change, and it is an important decision either way.&lt;/p&gt;</description></item><item><title>The Key to Your Locks (A Month of Activity Monitoring, Part 22 of 30)</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2011/04/22/the-key-to-your-locks-a-month-of-activity-monitoring-part-22-of-30.aspx</link><pubDate>Fri, 22 Apr 2011 14:00:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:34996</guid><dc:creator>Adam Machanic</dc:creator><description>&lt;p&gt;&lt;i&gt;This post is part 22 of a 30-part series about the &lt;a href="http://sqlblog.com/files/folders/35240/download.aspx"&gt;Who is Active&lt;/a&gt; stored procedure. A new post will run each day during the month of April, 2011. After April all of these posts will be edited and combined into a single document to become the basis of the Who is Active documentation.&lt;/i&gt;&lt;/p&gt;    &lt;hr&gt;    &lt;p&gt;&lt;u&gt;Note&lt;/u&gt;: Before reading this post, please &lt;a href="http://sqlblog.com/files/folders/35240/download.aspx"&gt;download the most recent Who is Active build&lt;/a&gt;, which includes a key fix for the locks mode.&lt;/p&gt;  &lt;hr&gt;   &lt;p&gt;&lt;b&gt;Blocking has been a theme of a &lt;/b&gt;&lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/14/blocking-blockers-and-other-b-words-a-month-of-activity-monitoring-part-14-of-30.aspx"&gt;&lt;b&gt;couple&lt;/b&gt;&lt;/a&gt;&lt;b&gt; of &lt;/b&gt;&lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/19/why-am-i-blocked-a-month-of-activity-monitoring-part-19-of-30.aspx"&gt;&lt;b&gt;recent&lt;/b&gt;&lt;/a&gt;&lt;b&gt; posts in this series. &lt;/b&gt;And that’s not even the end of it. Helping you find and properly evaluate blocking issues is a core part of Who is Active’s &lt;i&gt;raison d'être&lt;/i&gt;.&lt;/p&gt;  &lt;p&gt;Behind every block is something causing the block. Something that, without which, there could be no block. And that thing is called a &lt;i&gt;lock&lt;/i&gt;.&lt;/p&gt;  &lt;p&gt;Locks are synchronization objects. Their mission in life is not to give you headaches when dealing with blocking issues, but rather to help maintain the ACID properties that are a big part of the reason that DBMS technology is so popular. For locks in particular this means the “I” property: Isolation. (And, to a lesser extent, the "C" property: Consistency.) Locks keep readers from reading data that writers haven’t finished writing, and they keep writers from overwriting data as it’s being read or written by someone else. This is a good thing. Failure to take these kinds of precautions would result in chaos. And a lot of really bad data.&lt;/p&gt;  &lt;p&gt;When a DBA sees blocking, her first instinct is to eliminate it. Kill the blocker! Add a &lt;i&gt;NOLOCK&lt;/i&gt; hint! Change the processes around! But blocking is not necessarily a bad thing. Blocking means that your data is being protected. Readers are getting consistent results. Writers aren’t overwriting each other. Everything is as it should be—even if your queries are waiting an inordinate amount of time for data. &lt;/p&gt;  &lt;p&gt;&lt;b&gt;When you see blocking, the correct move is not to eliminate it, but rather to &lt;i&gt;evaluate&lt;/i&gt; it&lt;/b&gt;. Figure out what’s causing the blocking. Figure out why (or whether) it’s necessary, and what the alternatives might be. Then—and only then—should you start killing sessions, adding hints, or taking similar action.&lt;/p&gt;  &lt;p&gt;Evaluating blocking can be a painful experience. The &lt;i&gt;sys.dm_tran_locks&lt;/i&gt; view (formerly &lt;i&gt;syslockinfo&lt;/i&gt;) contains a large number of columns. Many of these are numeric values that need to be referenced elsewhere in order to be meaningful to the average human. And even then, it’s simply not a very nice user experience...&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/adam_machanic/F21_01_tran_locks_2AAA76FE.jpg"&gt;&lt;img src="http://sqlblog.com/blogs/adam_machanic/F21_01_tran_locks_thumb_3018E7A2.jpg" style="background-image:none;border-width:0px;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;" title="F21_01_tran_locks" alt="F21_01_tran_locks" border="0" height="349" width="712"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Glancing at this list of lock information, it’s impossible to tell what’s going on&lt;/b&gt;. (The query I ran to pull up this list returned 2700 rows.) &lt;/p&gt;  &lt;p&gt;Who is Active solves this problem by putting locks into a somewhat more human-readable form: a custom XML format. The stored procedure does all of the work of going to the databases with locks and decoding the numbers. So instead of seeing something like &lt;i&gt;72057594038845440&lt;/i&gt;, you’ll see something like &lt;i&gt;Sales.SalesOrderHeader&lt;/i&gt;. Whether or not you think that XML in general is a very readable format, the fact that the various object names have been resolved for you makes it a lot better than a straight query against &lt;i&gt;sys.dm_tran_locks&lt;/i&gt;.&lt;/p&gt;  &lt;p&gt;&lt;b&gt;To get lock information, use Who is Active’s &lt;i&gt;@get_locks = 1&lt;/i&gt; option&lt;/b&gt;. This will add a column called [locks] to the output. The column is typed as XML, and you can click on it to see the full contents. The document will have one root node per database in which there are locks. For the table listed above, the collapsed nodes look like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/adam_machanic/F21_02_locks_database_35F38B3B.jpg"&gt;&lt;img src="http://sqlblog.com/blogs/adam_machanic/F21_02_locks_database_thumb_072DD299.jpg" style="background-image:none;border:0px none;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;" title="F21_02_locks_database" alt="F21_02_locks_database" border="0" height="70" width="356"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Under each database node is one node that represents locks on the database itself, and a node called &lt;i&gt;Objects&lt;/i&gt; that contains subnodes for each object in the database that’s locked. These are grouped by object name and schema name:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/adam_machanic/F21_03_locks_object_06556CAF.jpg"&gt;&lt;img src="http://sqlblog.com/blogs/adam_machanic/F21_03_locks_object_thumb_20B55FC6.jpg" style="background-image:none;border:0px none;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;" title="F21_03_locks_object" alt="F21_03_locks_object" border="0" height="343" width="605"&gt;&lt;/a&gt;&lt;/p&gt;        &lt;p&gt;Any given object can have multiple types of active locks issued against it at one time, so inside of the &lt;i&gt;Object&lt;/i&gt; nodes are one or more &lt;i&gt;Lock&lt;/i&gt; nodes:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/adam_machanic/F22_04_locks_6AD06AAB.jpg"&gt;&lt;img src="http://sqlblog.com/blogs/adam_machanic/F22_04_locks_thumb_7E11214A.jpg" style="background-image:none;border:0px none;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;" title="F22_04_locks" alt="F22_04_locks" border="0" height="440" width="540"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;This format allows for quick and simple exploration of the various locks that are active on behalf of your session. Each &lt;i&gt;Lock&lt;/i&gt; node has an attribute called &lt;i&gt;request_status&lt;/i&gt;. If its value is “GRANT,” the lock is held by the session. If its value is “WAIT,” the request is waiting to acquire the lock.&lt;/p&gt;  &lt;p&gt;A full description of the various lock types is well beyond the scope of this post, but most of them are documented in the &lt;a href="http://msdn.microsoft.com/en-us/library/ms190345.aspx"&gt;Books Online entry for sys.dm_tran_locks&lt;/a&gt;&lt;i&gt;&lt;/i&gt;.&lt;/p&gt;  &lt;p&gt;&lt;b&gt;A cautionary note&lt;/b&gt;: Using the &lt;i&gt;@get_locks&lt;/i&gt; option can seriously slow down Who is Active. The &lt;i&gt;sys.dm_tran_locks&lt;/i&gt; DMV is known to be one of the slowest DMVs, and in some cases it can hold a huge number of rows. I have seen numerous cases where a simple &lt;i&gt;SELECT *&lt;/i&gt; against the DMV took 20 or more minutes to finish. When dealing with locks, which can change rapidly, that’s far too much elapsed time for the results to be meaningful. Recent Who is Active builds include &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2011/04/19/why-am-i-blocked-a-month-of-activity-monitoring-part-19-of-30.aspx"&gt;blocked object resolution&lt;/a&gt; mode, which is designed to be a much lighter weight alternative to using the full locks mode.&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;u&gt;Homework&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;Using the various DMVs it’s possible to write a number of queries that can deeply analyze block situations. Although Who is Active already does this, it’s an interesting exercise. Can you write a query that shows all blocked requests, the lock mode for each request, the blocker session or request that the blockees are waiting on, and the blocker lock mode?&lt;/p&gt;</description></item><item><title>Analyzing Tempdb Contention (A Month of Activity Monitoring, Part 21 of 30)</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2011/04/21/analyzing-tempdb-contention-a-month-of-activity-monitoring-part-21-of-30.aspx</link><pubDate>Thu, 21 Apr 2011 14:00:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:34995</guid><dc:creator>Adam Machanic</dc:creator><description>&lt;p&gt;&lt;i&gt;This post is part 21 of a 30-part series about the &lt;a href="http://sqlblog.com/files/folders/35240/download.aspx"&gt;Who is Active&lt;/a&gt; stored procedure. A new post will run each day during the month of April, 2011. After April all of these posts will be edited and combined into a single document to become the basis of the Who is Active documentation.&lt;/i&gt;&lt;/p&gt;  &lt;hr&gt;  &lt;p&gt;&lt;b&gt;&lt;i&gt;Tempdb&lt;/i&gt;. Everyone’s favorite shared bottleneck.&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;The funny thing about &lt;i&gt;tempdb&lt;/i&gt; is that it’s not used by every query. It’s only really used by the &lt;i&gt;biggest&lt;/i&gt; queries. The queries where performance really matters. And of course, that makes the situation all the worse. When &lt;i&gt;tempdb&lt;/i&gt; is a problem, it’s a &lt;i&gt;major problem&lt;/i&gt;.&lt;/p&gt;  &lt;p&gt;A common cause of &lt;i&gt;tempdb&lt;/i&gt; issues is &lt;i&gt;latch contention&lt;/i&gt;. This occurs due to three “special” page types: GAM (Global Allocation Map), SGAM (Shared Global Allocation Map), and PFS (Page Free Space). Each of these pages (sometimes many of each) exist in all database files, and they are responsible for helping to identify where incoming data can be written in the physical file. For complete background, &lt;a href="http://blogs.msdn.com/b/sqlserverstorageengine/archive/2006/07/08/under-the-covers-gam-sgam-and-pfs-pages.aspx"&gt;read this post by Paul Randal&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Whenever a process needs to update one of these special pages, a &lt;i&gt;latch&lt;/i&gt; is taken. A latch can be thought of as a kind of very lightweight lock; it’s designed for synchronization and is intended to be quickly turned on, and then just as quickly turned off after it’s no longer needed. The problem occurs when lots of processes happen to hit the SQL Server instance at the exact same time, and they all need to find a place to store some data. Suddenly, there are numerous outstanding latch requests. They start queuing up, and before you know it the last one in line has been waiting for seconds—and not doing any work at all in the meantime.&lt;/p&gt;  &lt;p&gt;Seeing this in action is quite simple. Create a bunch of temporary tables, in a very short period of time. I like to demo this using &lt;a href="http://www.datamanipulation.net/sqlquerystress"&gt;SQLQueryStress&lt;/a&gt;. Ideally you should do this kind of test on a server with only a single &lt;i&gt;tempdb&lt;/i&gt; data file, to really highlight the issue. Here’s the code to run:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;SELECT TOP(10000)       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; a.*        &lt;br&gt;INTO #x        &lt;br&gt;FROM         &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; master..spt_values a,         &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; master..spt_values b&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;20 or so concurrent threads should do it. Hit the start button in your load tool, wait a few seconds, run Who is Active, and you’ll see something similar to:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/adam_machanic/F21_01_latch_waits_16AC82B7.jpg"&gt;&lt;img src="http://sqlblog.com/blogs/adam_machanic/F21_01_latch_waits_thumb_17C0AA2F.jpg" style="background-image:none;border:0px none;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;" title="F21_01_latch_waits" alt="F21_01_latch_waits" border="0" height="167" width="717"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;See those &lt;i&gt;PAGELATCH&lt;/i&gt; waits?&lt;/b&gt; They’re all on the same resource: PFS pages, in &lt;i&gt;tempdb&lt;/i&gt; file ID 1. The format for &lt;i&gt;PAGELATCH&lt;/i&gt; and &lt;i&gt;PAGEIOLATCH&lt;/i&gt; waits is: &lt;i&gt;[wait_type]:[database_name]:[file_id](page_type)&lt;/i&gt;. Who is Active can decode the page types for GAM, SGAM, PFS, DCM (Differential Change Map), and BCM (Bulk Change Map) pages. For any other page, the page type will be an asterisk (*).&lt;/p&gt;&lt;p&gt;These waits are all on &lt;i&gt;update&lt;/i&gt; (UP) latches, but it's also quite common to see &lt;i&gt;exclusive&lt;/i&gt; (EX) latches when this problem occurs&lt;br&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Fixing this problem is amazingly simple&lt;/b&gt;: just create more &lt;i&gt;tempdb&lt;/i&gt; files! When you create additional &lt;i&gt;tempdb&lt;/i&gt; files—as long as they’re equally sized—SQL Server will automatically balance incoming requests across the multiple files. Since each file maintains its own PFS, GAM, and SGAM information, the contention will be eliminated.&lt;/p&gt;  &lt;p&gt;How many files should you create? Well, that depends on your workload. I take a simple approach: start with a number of files equal to one quarter to one half of the number of logical schedulers. If the contention goes away (i.e. Who is Active is no longer showing &lt;i&gt;PAGELATCH&lt;/i&gt; waits on these special pages in &lt;i&gt;tempdb&lt;/i&gt;), stop there. Otherwise, keep increasing the number of files until the contention does go away.&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Again: make sure to keep the files equally sized!&lt;/b&gt; SQL Server’s algorithm is based on a &lt;i&gt;proportional fill&lt;/i&gt; model, which means that if one file is bigger than the others it will be chosen more often. This will cause it to grow more quickly, which will cause it to be chosen more often, which will cause it to grow more quickly, which will keep compounding until your disk is full and your performance is back in the red zone. Not a good situation to get yourself into. Grow the files bigger than you need them at create time, and monitor to make sure things don’t get out of hand.&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;u&gt;Homework&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;Use Who is Active to check your production servers for &lt;i&gt;tempdb&lt;/i&gt; contention! Tell me in the comments below whether you found any. It’s amazing how common this issue is, yet how simple the fix turns out to be. A very satisfying task for even the most harried of DBAs.&lt;/p&gt;</description></item></channel></rss>