<?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 'Performance' and 'DMVs'</title><link>http://sqlblog.com/search/SearchResults.aspx?o=DateDescending&amp;tag=Performance,DMVs&amp;orTags=0</link><description>Search results matching tags 'Performance' and 'DMVs'</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>A Warning to Those Using sys.dm_exec_query_stats</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2010/04/22/a-warning-to-those-using-sys-dm-exec-query-stats.aspx</link><pubDate>Fri, 23 Apr 2010 02:15:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:24515</guid><dc:creator>Adam Machanic</dc:creator><description>&lt;p&gt;The sys.dm_exec_query_stats view is one of my favorite DMVs. It has replaced a large chunk of what I used to use SQL Trace for--pulling metrics about what queries are running and how often--and it makes this kind of data collection painless and automatic. What's not to love? But use cases for the view are a topic for another post. Today I want to quickly point out an inconsistency.&lt;/p&gt;
&lt;p&gt;If you're using this view heavily, as I am, you should know that in some cases your queries will not get a row. One such case, as it turns out, is any time an ALTER TABLE appears in your batch. "No big deal," you might be thinking. "I don't regularly alter tables in stored procedures." But think again. Do you ever create a temporary table using SELECT INTO? Do you ever create indexes on the resultant table? I know I do--and quite often those indexes are primary keys, or unique constraints.&lt;/p&gt;
&lt;p&gt;The interesting thing is that CREATE INDEX does not suffer from this problem. You can create unique indexes all day long and still get entries in the query stats DMV. And thus the inconsistency: Using ALTER TABLE to create a primary key or unique constraint on a temporary table is, for all intents and purposes &lt;i&gt;exactly the same thing&lt;/i&gt; as creating a unique index using CREATE INDEX. But one works with the query_stats DMV and the other doesn't.&lt;/p&gt;
&lt;p&gt;It's not difficult to imagine how this inconsistency arose; just rather annoying in practice. I went through a bunch of code today and changed several instances of ALTER TABLE to CREATE INDEX, and my monitoring scripts are already working better as a result. I recommend that you take the time to do the same, if you use this view.&lt;br&gt;&lt;/p&gt;
&lt;p&gt;To conclude this post, a quick repro so that you can see the issue:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;SELECT&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'abc' AS a&lt;br&gt;INTO #x&lt;br&gt;&lt;br&gt;ALTER TABLE #x&lt;br&gt;ADD UNIQUE (a)&lt;br&gt;&lt;br&gt;SELECT *&lt;br&gt;FROM sys.dm_exec_query_stats&lt;br&gt;WHERE&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; plan_handle IN&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; plan_handle&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM sys.dm_exec_requests&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHERE&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session_id = @@SPID&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br&gt;&lt;br&gt;DROP TABLE #x&lt;br&gt;GO&lt;br&gt;&lt;br&gt;&lt;br&gt;SELECT&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'abc' AS a&lt;br&gt;INTO #x&lt;br&gt;&lt;br&gt;CREATE UNIQUE INDEX whatever&lt;br&gt;ON #x (a)&lt;br&gt;&lt;br&gt;SELECT *&lt;br&gt;FROM sys.dm_exec_query_stats&lt;br&gt;WHERE&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; plan_handle IN&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; plan_handle&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM sys.dm_exec_requests&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHERE&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session_id = @@SPID&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br&gt;&lt;br&gt;DROP TABLE #x&lt;br&gt;GO&lt;br&gt;&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Enjoy, and best of luck in all of your monitoring endeavors. &lt;br&gt;&lt;/p&gt;</description></item><item><title>Who is Active? v9.57: Fast, Comprehensive DMV Collection - What's Really Happening on Your Server?</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2009/12/03/who-is-active-v9-57-fast-comprehensive-dmv-collection.aspx</link><pubDate>Thu, 03 Dec 2009 19:59:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:19489</guid><dc:creator>Adam Machanic</dc:creator><description>
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h1&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;&lt;b&gt;UPDATE, April 28 2011: Who is Active v9.57 is outdated. Please use v11.00 instead.&lt;/b&gt;&lt;/a&gt;&lt;/h1&gt;&lt;br&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;hr&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Happy December, SQLblog readers! My gift to you, just in time for the holidays: The newest "official" release of your favorite &lt;b&gt;SQL Server activity monitoring stored procedure&lt;/b&gt;.&lt;span class="status"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlblog.com/files/folders/19491/download.aspx"&gt;&lt;b&gt;Click here to download Who is Active? v9.57&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Since the last release--&lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2009/08/20/who-is-active-v8-82-harder-better-faster-stronger.aspx"&gt;v8.82, from August of this year&lt;/a&gt;--I've made a number of modifications to the script, resulting in six interim "beta" releases. The uniting theme of all of these changes is &lt;b&gt;more, better quality data, faster&lt;/b&gt;. &lt;/p&gt;
&lt;p&gt;&lt;b&gt;More data&lt;/b&gt;. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Two new core options were added at the behest of users: &lt;b&gt;@show_sleeping_spids&lt;/b&gt; and &lt;b&gt;@show_system_spids&lt;/b&gt;. These options cause the procedure to return information that wasn't previously available via Who is Active, about--you guessed it--sleeping and system sessions, respectively. &lt;br&gt;&lt;/li&gt;
&lt;li&gt;Another major change was adding a feature so that &lt;b&gt;the script now shows blocking sessions whether or not they're included in the default filter criteria&lt;/b&gt;. This is not something you turn on or off--it just happens--and will ensure that if you're debugging a blocking scenario you'll automatically have all the information you need. &lt;br&gt;&lt;/li&gt;
&lt;li&gt;And for you query plan geeks out there, the full wait stats collection mode (see the "Faster data" section below) now returns node identifier information with CXPACKET waits--helping you to &lt;b&gt;track progress of tasks as a plan is executed&lt;/b&gt;. &lt;br&gt;&lt;/li&gt;
&lt;li&gt;Finally, a small modification. The online help system (@help=1) now returns information about both the available input parameters as well as all of the available output columns.&lt;br&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Better data&lt;/b&gt;.&lt;b&gt; &lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A few minor &lt;b&gt;bugs were fixed&lt;/b&gt;, mostly &lt;b&gt;having to do with the evils of MARS&lt;/b&gt; and the fact that the DMVs don't properly deal with MARS sessions in many cases. &lt;br&gt;&lt;/li&gt;
&lt;li&gt;Workarounds were also added for inconsistencies in how the DMVs report SQL handles, even without MARS. &lt;br&gt;&lt;/li&gt;
&lt;li&gt;Two features were added to help you get only the data you need when you need it, and not the data you don't:&amp;nbsp;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Dynamic sort ordering&lt;/b&gt;, via a parameter called @sort_order, lets you pass in a list of columns and column directions by which to sort the output. &lt;br&gt;&lt;/li&gt;
&lt;li&gt;And &lt;b&gt;"not" filters&lt;/b&gt;, implemented using parameters @not_filter and @not_filter_type, work exactly the opposite of regular filters. These are useful in those cases where you have a bunch of sessions that aren't of interest, and you don't want them cluttering your output. &lt;br&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Finally, I've &lt;b&gt;changed the default output column order&lt;/b&gt; to something I think is a bit more useful. Don't like my selections? No problem--override me using the @output_column_list parameter.&lt;br&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Faster data&lt;/b&gt;. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This is the area in which I made the most modifications. &lt;b&gt;A monitoring tool borders on useless when it takes a minute or more to return key metrics&lt;/b&gt; when your server is on fire, and alas, previous versions of Who is Active were doing just that for some users. &lt;br&gt;&lt;/li&gt;
&lt;li&gt;I've made major changes to the core queries in this version of Who is Active, &lt;b&gt;bringing down query times from minutes to a few seconds&lt;/b&gt; in many cases. &lt;br&gt;&lt;/li&gt;
&lt;li&gt;In conjunction with these changes I added a new &lt;b&gt;lightweight wait stats collection&lt;/b&gt; mode, which is the new default. This mode collects only the top non-CXPACKET wait, giving preference to blocked waits, so that you can see the worst problems without having to sort through a lot of output that may or may not apply. &lt;br&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;If you miss the complete stats collection mode, it's still there--simply set @get_task_info=2 when calling the procedure.&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;p&gt;I'm quite happy with this release, and I hope that it will help people quickly solve a number of tricky SQL Server problems. &lt;b&gt;As always, your feedback is very much appreciated!&lt;/b&gt; Leave me a comment here, e-mail me (my address is in the script), or track me down at a conference. Most of the features in the past few versions are a direct result of requests I've gotten from users. &lt;/p&gt;
&lt;p&gt;A &lt;b&gt;huge thank you to those who tested and gave me feedback&lt;/b&gt; since the last version! Aaron Bertrand, Rajiv Jain, Michelle Ufford, Uri Dimant, and everyone else, I really am thankful for your efforts. To these people and all of my readers, &lt;b&gt;I wish you a happy December and a prosperous 2010&lt;/b&gt;. &lt;/p&gt;
&lt;p&gt;Until next time, enjoy!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;a href="http://sqlblog.com/files/folders/19491/download.aspx"&gt;&lt;b&gt;Click here to download Who is Active? v9.57&lt;/b&gt;&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Please ignore the text below. Putting in it for search purposes.&lt;/p&gt;
&lt;p&gt;sp_whoisactive whoisactive sp_who sp_who2 sp_who3 sp_who4 sp_who5&lt;br&gt;&lt;/p&gt;</description></item><item><title>The Hidden Costs of INSERT EXEC</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2009/06/25/the-hidden-costs-of-insert-exec.aspx</link><pubDate>Thu, 25 Jun 2009 20:19:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:14921</guid><dc:creator>Adam Machanic</dc:creator><description>&lt;p&gt;INSERT and EXEC: relational brothers in arms, helping you get your
data and then put it somewhere. But like all brothers, their
relationship has its ups and downs and sometimes you need to look just
below the surface to see the real issues. In this post I will cover
hidden penalties that a decision--seemingly purely aesthetic--can bring
to the fore.&lt;/p&gt;

&lt;p&gt;To illustrate the first of these examples I will be using the following table:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;p&gt;USE tempdb&lt;br&gt;GO&lt;br&gt;&lt;/p&gt;&lt;br&gt;CREATE TABLE dbo.MyTable&lt;br&gt;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [SalesOrderID] [int] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [SalesOrderDetailID] [int] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [CarrierTrackingNumber] [nvarchar](25) NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [OrderQty] [smallint] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [ProductID] [int] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [SpecialOfferID] [int] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [UnitPrice] [money] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [UnitPriceDiscount] [money] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [LineTotal] [money] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [rowguid] [uniqueidentifier]&amp;nbsp; NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [ModifiedDate] [datetime] NOT NULL&lt;br&gt;)&lt;br&gt;GO&lt;br&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Consider the following queries, disregarding the fact that this
isn't a good dynamic SQL example (I'm trying to keep it simple), and
take a moment to think about the differences between them from a
behavioral point of view:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;EXEC&lt;br&gt;('&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; INSERT dbo.MyTable&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT *&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM AdventureWorks.Sales.SalesOrderDetail&lt;br&gt;')&lt;br&gt;GO&lt;br&gt;&lt;br&gt;INSERT dbo.MyTable&lt;br&gt;EXEC &lt;br&gt;('&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT *&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM AdventureWorks.Sales.SalesOrderDetail&lt;br&gt;')&lt;br&gt;GO&lt;br&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;It's quite common to insert some data into a table from dynamic SQL,
and for as long as I can remember, I've believed the choice between
these two forms of the query to be primarily an issue of style. My
preference has been for the latter style, as I feel that it's a bit
more readable. It also has the benefit of better supporting ownership
chains, but that's something that, in most cases, we don't have to
worry about any longer in SQL Server 2005 or 2008. But let's move
beyond style and potential security issues and get to the substance.
What actually happens when we run these two queries?&lt;/p&gt;

&lt;p&gt;In the first case--insert done inside of the EXEC--the first step is
that the outer statement--the EXEC itself--is parsed and validated. Now
we jump down one level of context, into the string that was passed to
EXEC, and that string is parsed and validated. The referenced objects
are resolved, and the plan cache is checked. If there is no plan, the
query is compiled. And then it's executed. Data is streamed from
SalesOrderDetail into MyTable and when the query inside of the EXEC is
done control returns to the calling context--EXEC--and assuming there
were no errors, the EXEC is now completed.&lt;/p&gt;

&lt;p&gt;In the second case, something quite a bit different occurs. The
insert is parsed and validated, and an INSERT EXEC plan is generated.
This plan does not involve SalesOrderDetail, as the query optimizer
doesn't know at this point in the process where the data will be
inserted from, since that step is dynamic. So the plan references
something called the "Parameter Table" (plan truncated for simplicity):&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;p&gt;|--Table Insert(OBJECT:([tempdb].[dbo].[MyTable]))&lt;br&gt;&amp;nbsp;&amp;nbsp; |--Top(ROWCOUNT est 0)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |--Parameter Table Scan&lt;br&gt;&lt;/p&gt;&lt;br&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once this plan has been generated, we again jump down one level of
context, and the inner string is parsed and validated, the referenced
object resolved, the cache checked, and the compiled plan executed. But
what is this Parameter Table thing? &lt;/p&gt;

&lt;p&gt;Here's where things start really diverging. Data is not, at this
point, streamed from SalesOrderDetail directly into MyTable. Rather, it
is streamed from SalesOrderDetail into the Parameter Table. And the
Parameter Table, as it turns out, is in actuality a hidden temporary
table. And not until all of the data has streamed into that hidden
temporary table is control resumed by the EXEC context, and only then
does the data start moving into its final home. &lt;/p&gt;

&lt;p&gt;The natural question you might be asking yourself at this point is,
just how much overhead does this Parameter Table introduce into the
equation? The answer might just send you racing to check your stored
procedures: the additional cost for the Parameter Table is well over
100% as compared with doing the insert inside of the EXEC. The fact
that all of the data must be spooled to the Parameter Table before the
insert can even begin tells us that this must be true, and it can be
verified using a simple check against the sys.dm_exec_requests DMV, as
in the following example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;p&gt;EXEC&lt;br&gt;('&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; INSERT dbo.MyTable&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT *&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM AdventureWorks.Sales.SalesOrderDetail&lt;br&gt;')&lt;br&gt;&lt;br&gt;SELECT&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; r.writes AS [INSERT inside EXEC writes]&lt;br&gt;FROM sys.dm_exec_requests r&lt;br&gt;WHERE &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; r.session_id = @@SPID&lt;br&gt;GO&lt;br&gt;&lt;br&gt;INSERT dbo.MyTable&lt;br&gt;EXEC&lt;br&gt;('&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT *&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM AdventureWorks.Sales.SalesOrderDetail&lt;br&gt;')&lt;br&gt;&lt;br&gt;SELECT&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; r.writes AS [INSERT EXEC writes]&lt;br&gt;FROM sys.dm_exec_requests r&lt;br&gt;WHERE &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; r.session_id = @@SPID&lt;br&gt;GO&lt;br&gt;&lt;/p&gt;&lt;br&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;So that's that. We should avoid INSERT EXEC and try to do our inserts in the same context in which the SELECT is running--right?&lt;/p&gt;

&lt;p&gt;Well, yes and no. There is another element at play here which I
haven't yet mentioned. What if we were only inserting a few rows, and
the table we were inserting into looked something like the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;p&gt;CREATE TABLE #MyTable&lt;br&gt;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [SalesOrderID] [int] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [SalesOrderDetailID] [int] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [CarrierTrackingNumber] [nvarchar](25) NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [OrderQty] [smallint] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [ProductID] [int] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [SpecialOfferID] [int] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [UnitPrice] [money] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [UnitPriceDiscount] [money] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [LineTotal] [money] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [rowguid] [uniqueidentifier]&amp;nbsp; NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [ModifiedDate] [datetime] NOT NULL&lt;br&gt;)&lt;br&gt;GO&lt;/p&gt;&lt;br&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;The only difference between this table and the previous one is that
this is a temporary table and the other is not. But temporary tables
have their own interesting little twists, especially when it comes down
to one of the key enemies in a highly-transactional system:
recompilation. As it turns out, doing the insert inside the EXEC will
cause the internal statement to recompile every time a new temp table
is encountered. This means that if you have a stored procedure that
creates a temp table, puts together a bit of dynamic SQL, and does an
insert inside of that dynamic SQL, you'll now have yourself a
recompilation problem.&lt;/p&gt;


&lt;p&gt;To see this illustrated, try the following script. Here only a
single row is inserted as a result of the dynamic query, but it's
complex enough that the compile time more than overshadows the overhead
of the Parameter Table:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;p&gt;USE tempdb&lt;br&gt;GO&lt;br&gt;&lt;br&gt;DBCC FREEPROCCACHE&lt;br&gt;GO&lt;br&gt;&lt;br&gt;CREATE TABLE #AvgTimes&lt;br&gt;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CPU_time DECIMAL(19,4) NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; insert_type VARCHAR(25) NOT NULL&lt;br&gt;)&lt;br&gt;GO&lt;br&gt;&lt;br&gt;CREATE TABLE #MyTable&lt;br&gt;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [SalesOrderID] [int] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [SalesOrderDetailID] [int] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [CarrierTrackingNumber] [nvarchar](25) NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [OrderQty] [smallint] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [ProductID] [int] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [SpecialOfferID] [int] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [UnitPrice] [money] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [UnitPriceDiscount] [money] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [LineTotal] [money] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [rowguid] [uniqueidentifier]&amp;nbsp; NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [ModifiedDate] [datetime] NOT NULL&lt;br&gt;)&lt;br&gt;&lt;br&gt;EXEC&lt;br&gt;('&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; INSERT #MyTable&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT TOP(1)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; sod.*&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM AdventureWorks.Sales.SalesOrderDetail sod&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHERE &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; sod.UnitPrice &amp;gt; 10&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; AND sod.LineTotal &amp;gt; 100&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; AND EXISTS&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT *&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; FROM AdventureWorks.Sales.SalesOrderHeader soh&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; JOIN AdventureWorks.Person.Contact c ON &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; c.ContactID = soh.CustomerID&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; WHERE&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; soh.SalesOrderID = sod.SalesOrderID&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; AND c.LastName LIKE ''Ab%''&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; AND EXISTS&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT *&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; FROM AdventureWorks.Production.Product p&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; WHERE&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; p.ProductID = sod.ProductID&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; AND p.Color IS NULL&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; AND NOT EXISTS&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT *&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; FROM AdventureWorks.Sales.SalesOrderHeader soh&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; JOIN AdventureWorks.Sales.SalesPerson sp ON&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; soh.SalesPersonID = sp.SalesPersonID&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; WHERE&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; soh.SalesOrderID = sod.SalesOrderID&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; AND sp.CommissionPct &amp;gt; 50&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br&gt;')&lt;br&gt;&lt;br&gt;INSERT #AvgTimes&lt;br&gt;SELECT&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; r.cpu_time,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'INSERT inside EXEC'&lt;br&gt;FROM sys.dm_exec_requests r&lt;br&gt;WHERE &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; r.session_id = @@SPID&lt;br&gt;&lt;br&gt;DROP TABLE #MyTable&lt;br&gt;GO 5&lt;br&gt;&lt;br&gt;CREATE TABLE #MyTable&lt;br&gt;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [SalesOrderID] [int] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [SalesOrderDetailID] [int] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [CarrierTrackingNumber] [nvarchar](25) NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [OrderQty] [smallint] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [ProductID] [int] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [SpecialOfferID] [int] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [UnitPrice] [money] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [UnitPriceDiscount] [money] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [LineTotal] [money] NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [rowguid] [uniqueidentifier]&amp;nbsp; NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [ModifiedDate] [datetime] NOT NULL&lt;br&gt;)&lt;br&gt;&lt;br&gt;INSERT #MyTable&lt;br&gt;EXEC&lt;br&gt;('&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT TOP(1)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; sod.*&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM AdventureWorks.Sales.SalesOrderDetail sod&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHERE &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; sod.UnitPrice &amp;gt; 10&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; AND sod.LineTotal &amp;gt; 100&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; AND EXISTS&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT *&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; FROM AdventureWorks.Sales.SalesOrderHeader soh&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; JOIN AdventureWorks.Person.Contact c ON &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; c.ContactID = soh.CustomerID&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; WHERE&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; soh.SalesOrderID = sod.SalesOrderID&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; AND c.LastName LIKE ''Ab%''&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; AND EXISTS&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT *&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; FROM AdventureWorks.Production.Product p&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; WHERE&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; p.ProductID = sod.ProductID&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; AND p.Color IS NULL&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; AND NOT EXISTS&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT *&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; FROM AdventureWorks.Sales.SalesOrderHeader soh&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; JOIN AdventureWorks.Sales.SalesPerson sp ON&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; soh.SalesPersonID = sp.SalesPersonID&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; WHERE&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; soh.SalesOrderID = sod.SalesOrderID&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; AND sp.CommissionPct &amp;gt; 50&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br&gt;')&lt;br&gt;&lt;br&gt;INSERT #AvgTimes&lt;br&gt;SELECT&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; r.cpu_time,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'INSERT EXEC'&lt;br&gt;FROM sys.dm_exec_requests r&lt;br&gt;WHERE &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; r.session_id = @@SPID&lt;br&gt;&lt;br&gt;DROP TABLE #MyTable&lt;br&gt;GO 5&lt;br&gt;&lt;br&gt;SELECT &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; AVG&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; CASE a.insert_type &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 'INSERT inside EXEC' THEN a.CPU_time&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ELSE NULL&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; END&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ) AS [CPU time - INSERT inside EXEC],&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; AVG&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; CASE a.insert_type &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 'INSERT EXEC' THEN a.CPU_time&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ELSE NULL&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; END&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ) AS [CPU time - INSERT EXEC]&lt;br&gt;FROM #AvgTimes a&lt;br&gt;GO&lt;br&gt;&lt;br&gt;DROP TABLE #AvgTimes&lt;br&gt;GO&lt;/p&gt;&lt;br&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;So what have we learned today? The choice between INSERT EXEC and
INSERT inside of EXEC is not purely stylistic and has definite
performance implications. Here are the rules I'll be following from now
on:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;When working with permanent tables, always avoid INSERT EXEC if
possible. There are some cases where it won't be possible to avoid. I
only showed dynamic SQL in this post, but INSERT EXEC also applies to
stored procedures. Can you safely rip apart all of the stored
procedures in your system in order to avoid this issue? Maybe not quite
as easily as you can rip apart the dynamic SQL within stored procedures.&lt;/li&gt;&lt;li&gt;When working with temporary tables, evaluate the complexity of the
operations, the amount of data to be inserted, and most importantly,
test every solution! The more rows that are inserted as a result of the
INSERT EXEC, the more the overhead you'll get from the Parameter Table.
On the flip side, the more complex the dynamic statement, the more
overhead you'll get from recompilations. Every scenario is bound to be
different and you may just learn something about your processes by
doing this extra bit of analysis.&lt;/li&gt;&lt;/ul&gt;
Enjoy!&lt;br&gt;</description></item><item><title>A Gift of Script for 2009: Who is Active, Redux</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2008/12/31/a-gift-of-script-for-2009-who-is-active-redux.aspx</link><pubDate>Wed, 31 Dec 2008 14:49:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:10841</guid><dc:creator>Adam Machanic</dc:creator><description>&lt;p&gt;Last year on December 31 &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2007/12/31/a-gift-of-script-for-2008-who-s-active-what-are-they-doing-and-who-is-blocked.aspx"&gt;I posted part of a larger monitoring script that I had been working on for a few months&lt;/a&gt;. I received lots of great feedback on the little script in both the comments and from people I was working with, and over the course of the last year I estimate that I have invested at least a couple of hundred hours in the script. &lt;a href="http://sqlblog.com/blogs/adam_machanic/attachment/10841.ashx"&gt;The result of all of this time is attached&lt;/a&gt;, and I hope that this script is as useful for others as it has been for me; I've been using it pretty much nonstop while modifying it and it has become an indispensable part of my toolkit. &lt;/p&gt;
&lt;p&gt;Alas, while I had planned to write a comprehensive blog post on the script for publication today, I simply don't have time to do it correctly at the moment--but I wanted to get the script out on the 31st in order to create a kind of tradition. So instead of telling you everything it can do, I will ask that you instead take a look inside the script, where I've done a fairly good job documenting both the parameters and the outputs.&amp;nbsp; I'll do a followup post soon (I hope) and do a better job of telling you about the various options.&amp;nbsp; In the meantime, I'll leave you with a list of the script's major features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Wait stats collection&lt;/b&gt;, if you enable the GET_WAITS switch. This mode aggregates the various resources that the tasks associated with the session are waiting on, and lets you know how long the tasks have been waiting.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Collection of lock information&lt;/b&gt;, if you enable the GET_LOCKS switch. A lot of effort went into this particular feature--all of the locks for each session are aggregated in an XML format, and work is done to map the various identifiers associated with each lock to actual object names so that you don't have to do the footwork yourself.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Information about sleeping SPIDs&lt;/b&gt; holding open transactions, if you enable the GET_TRANSACTION_INFO switch. If you're being blocked by a SPID that is not active, you should be able to find out about it. This option lets you do it.&amp;nbsp; As a bonus, it also pulls information about transaction log writes in any database in which the transaction has done a write.&lt;br&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Collection of the "outer" command/batch&lt;/b&gt;, if you enable the GET_OUTER_COMMAND switch. One of the comments on the script I posted last year asked why, if you issue SQL like "ALTER TABLE dbo.xx ALTER COLUMN yyy FLOAT NULL", you'll end up with statement text that looks like "UPDATE [zzz].[dbo].[xxx] SET [yyy] = [yyy]". This is an internal representation of what's actually happening, but in many cases is not esepecially useful for end-users. So if you want to see what was actually run, now you can.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Every expensive or potentially expensive option is now parameterized&lt;/b&gt;. I spent a lot of time tweaking performance and with no options running the thing is pretty fast. Enable some options--especially lock collection--and it will slow down considerably, so use these advanced features with care.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Enjoy, and &lt;b&gt;please keep sending feedback&lt;/b&gt;!&amp;nbsp; Let me know what else you would like to see, if you find bugs, etc.&amp;nbsp; I'll post updated versions as major changes are made. &lt;/p&gt;
&lt;p&gt;To finish I would like to thank a few of the people who had an impact on the evolution of this script over the past&amp;nbsp;12 months: Michael Condon, &lt;a href="http://sommarskog.se/"&gt;Erland Sommarskog&lt;/a&gt;, &lt;a href="http://sqlblog.com/blogs/aaron_bertrand/default.aspx"&gt;Aaron Bertrand&lt;/a&gt;, &lt;a href="http://sqlblog.com/blogs/louis_davidson/default.aspx"&gt;Louis Davidson&lt;/a&gt;, and &lt;a href="http://jmkehayias.blogspot.com/"&gt;Jonathan Kehayias&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Have a great 2009, everyone! &lt;br&gt;&lt;/p&gt;</description></item></channel></rss>