<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SQL Fool &#187; missing indexes</title>
	<atom:link href="http://sqlfool.com/tag/missing-indexes/feed/" rel="self" type="application/rss+xml" />
	<link>http://sqlfool.com</link>
	<description>Adventures in SQL Tuning - a blog for the rest of us</description>
	<lastBuildDate>Wed, 02 Nov 2011 20:39:11 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>A Look at Missing Indexes</title>
		<link>http://sqlfool.com/2009/04/a-look-at-missing-indexes/</link>
		<comments>http://sqlfool.com/2009/04/a-look-at-missing-indexes/#comments</comments>
		<pubDate>Tue, 28 Apr 2009 16:30:55 +0000</pubDate>
		<dc:creator>Michelle Ufford</dc:creator>
				<category><![CDATA[Performance & Tuning]]></category>
		<category><![CDATA[Syndication]]></category>
		<category><![CDATA[T-SQL Scripts]]></category>
		<category><![CDATA[indexes]]></category>
		<category><![CDATA[maintenace]]></category>
		<category><![CDATA[missing indexes]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://sqlfool.com/?p=868</guid>
		<description><![CDATA[Tim Ford (@SQLAgentMan) recently blogged about his Top 5 SQL Server Indexing Best Practices. I thought it was a good list, and it inspired this blog post. I've recently been doing a little index spring cleaning, and I thought some people may be interested in the process I go through. So, here it is... a [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.ford-it.com/sqlagentman/" target="_blank">Tim Ford</a> (<a href="http://twitter.com/sqlagentman">@SQLAgentMan</a>) recently blogged about his <a href="http://www.ford-it.com/sqlagentman/?p=206" target="_blank">Top 5 SQL Server Indexing Best Practices</a>.  I thought it was a good list, and it inspired this blog post.  I've recently been doing a little index spring cleaning, and I thought some people may be interested in the process I go through.  So, here it is... <span style="text-decoration: line-through;">a journey through madness</span> an overview of my general missing index process.</p>
<p>I start with my trusty dba_missingIndexStoredProc table.  If this table sounds completely foreign to you, check out my post, <a href="http://sqlfool.com/2009/03/find-missing-indexes/" target="_blank">Find Missing Indexes In Stored Procs</a>.  Basically, I have a process that runs every night, scanning the XML of every query plan on the server to find procs that are possibly missing indexes.  I then log the details for later action.</p>
<p>So I take a look at my table, and I find 8 stored procedures that are possibly missing indexes.  Clicking on the XML link will show me the logged query plan:</p>
<div id="attachment_869" class="wp-caption alignnone" style="width: 310px"><a href="http://sqlfool.com/wp-content/uploads/2009/04/20090428_1.jpg" target="_blank"><img src="http://sqlfool.com/wp-content/uploads/2009/04/20090428_1-300x78.jpg" alt="Procs With Missing Indexes" title="20090428_1" width="300" height="78" class="size-medium wp-image-869" /></a><p class="wp-caption-text">Procs With Missing Indexes</p></div>
<p>Right clicking on the "Missing Index" description will give me the details of the recommended index:</p>
<div id="attachment_870" class="wp-caption alignnone" style="width: 310px"><a href="http://sqlfool.com/wp-content/uploads/2009/04/20090428_2.jpg" target="_blank"><img src="http://sqlfool.com/wp-content/uploads/2009/04/20090428_2-300x138.jpg" alt="Missing Index Details" title="20090428_2" width="300" height="138" class="size-medium wp-image-870" /></a><p class="wp-caption-text">Missing Index Details</p></div>
<p>Here's an example of what SQL Server will return for you:</p>

<div class="wp_syntax"><div class="code"><pre class="tsql" style="font-family:monospace;"><span style="color: #008080;">/*
Missing Index Details from ExecutionPlan2.sqlplan
The Query Processor estimates that implementing the following index 
could improve the query cost by 85.7327%.
*/</span>
&nbsp;
<span style="color: #008080;">/*
USE [msdb]
GO
CREATE NONCLUSTERED INDEX [&lt;Name of Missing Index, sysname,&gt;]
ON [dbo].[sysjobhistory] ([job_id])
INCLUDE ([instance_id],[step_id],[sql_message_id],[sql_severity],
[run_status],[run_date],[run_time],[run_duration],[operator_id_emailed], 
[operator_id_netsent],[operator_id_paged],[retries_attempted],[server])
GO
*/</span></pre></div></div>

<p>I now compare the details of this proposed index to the missing index DMV suggestions, using this query:</p>

<div class="wp_syntax"><div class="code"><pre class="tsql" style="font-family:monospace;"><span style="color: #0000FF;">SELECT</span> t.<span style="color: #202020;">name</span> <span style="color: #0000FF;">AS</span> <span style="color: #FF0000;">'affected_table'</span>
    , <span style="color: #FF0000;">'Create NonClustered Index IX_'</span> <span style="color: #808080;">+</span> t.<span style="color: #202020;">name</span> <span style="color: #808080;">+</span> <span style="color: #FF0000;">'_missing_'</span> 
        <span style="color: #808080;">+</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span>ddmid.<span style="color: #202020;">index_handle</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">VARCHAR</span><span style="color: #808080;">&#40;</span><span style="color: #000;">10</span><span style="color: #808080;">&#41;</span><span style="color: #808080;">&#41;</span>
        <span style="color: #808080;">+</span> <span style="color: #FF0000;">' On '</span> <span style="color: #808080;">+</span> ddmid.<span style="color: #0000FF;">STATEMENT</span> 
        <span style="color: #808080;">+</span> <span style="color: #FF0000;">' ('</span> <span style="color: #808080;">+</span> IsNull<span style="color: #808080;">&#40;</span>ddmid.<span style="color: #202020;">equality_columns</span>,<span style="color: #FF0000;">''</span><span style="color: #808080;">&#41;</span> 
        <span style="color: #808080;">+</span> <span style="color: #0000FF;">CASE</span> <span style="color: #0000FF;">WHEN</span> ddmid.<span style="color: #202020;">equality_columns</span> <span style="color: #0000FF;">IS</span> Not Null 
            And ddmid.<span style="color: #202020;">inequality_columns</span> <span style="color: #0000FF;">IS</span> Not Null <span style="color: #0000FF;">THEN</span> <span style="color: #FF0000;">','</span> 
                <span style="color: #0000FF;">ELSE</span> <span style="color: #FF0000;">''</span> <span style="color: #0000FF;">END</span> 
        <span style="color: #808080;">+</span> IsNull<span style="color: #808080;">&#40;</span>ddmid.<span style="color: #202020;">inequality_columns</span>, <span style="color: #FF0000;">''</span><span style="color: #808080;">&#41;</span>
        <span style="color: #808080;">+</span> <span style="color: #FF0000;">')'</span> 
        <span style="color: #808080;">+</span> IsNull<span style="color: #808080;">&#40;</span><span style="color: #FF0000;">' Include ('</span> <span style="color: #808080;">+</span> ddmid.<span style="color: #202020;">included_columns</span> <span style="color: #808080;">+</span> <span style="color: #FF0000;">');'</span>, <span style="color: #FF0000;">';'</span>
        <span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> sql_statement
    , ddmigs.<span style="color: #202020;">user_seeks</span>
    , ddmigs.<span style="color: #202020;">user_scans</span>
    , <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #808080;">&#40;</span>ddmigs.<span style="color: #202020;">user_seeks</span> <span style="color: #808080;">+</span> ddmigs.<span style="color: #202020;">user_scans</span><span style="color: #808080;">&#41;</span> 
        <span style="color: #808080;">*</span> ddmigs.<span style="color: #202020;">avg_user_impact</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">INT</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #FF0000;">'est_impact'</span>
    , ddmigs.<span style="color: #202020;">last_user_seek</span>
<span style="color: #0000FF;">FROM</span> sys.<span style="color: #202020;">dm_db_missing_index_groups</span> <span style="color: #0000FF;">AS</span> ddmig
<span style="color: #0000FF;">INNER</span> <span style="color: #808080;">JOIN</span> sys.<span style="color: #202020;">dm_db_missing_index_group_stats</span> <span style="color: #0000FF;">AS</span> ddmigs
    <span style="color: #0000FF;">ON</span> ddmigs.<span style="color: #202020;">group_handle</span> <span style="color: #808080;">=</span> ddmig.<span style="color: #202020;">index_group_handle</span>
<span style="color: #0000FF;">INNER</span> <span style="color: #808080;">JOIN</span> sys.<span style="color: #202020;">dm_db_missing_index_details</span> <span style="color: #0000FF;">AS</span> ddmid 
    <span style="color: #0000FF;">ON</span> ddmig.<span style="color: #202020;">index_handle</span> <span style="color: #808080;">=</span> ddmid.<span style="color: #202020;">index_handle</span>
<span style="color: #0000FF;">INNER</span> <span style="color: #808080;">JOIN</span> sys.<span style="color: #202020;">tables</span> <span style="color: #0000FF;">AS</span> t
    <span style="color: #0000FF;">ON</span> ddmid.<span style="color: #FF00FF;">OBJECT_ID</span> <span style="color: #808080;">=</span> t.<span style="color: #FF00FF;">OBJECT_ID</span>
<span style="color: #0000FF;">WHERE</span> ddmid.<span style="color: #202020;">database_id</span> <span style="color: #808080;">=</span> <span style="color: #FF00FF;">DB_ID</span><span style="color: #808080;">&#40;</span><span style="color: #808080;">&#41;</span>
    <span style="color: #008080;">--AND t.name = 'myTableName' </span>
<span style="color: #0000FF;">ORDER</span> <span style="color: #0000FF;">BY</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #808080;">&#40;</span>ddmigs.<span style="color: #202020;">user_seeks</span> <span style="color: #808080;">+</span> ddmigs.<span style="color: #202020;">user_scans</span><span style="color: #808080;">&#41;</span> 
    <span style="color: #808080;">*</span> ddmigs.<span style="color: #202020;">avg_user_impact</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">INT</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">DESC</span>;</pre></div></div>

<p>I usually find the data in both places, but not always.  One reason why is because the missing index DMV will only store data since your last reboot.  So if I'm taking a look at this DMV on Monday and I just rebooted on Sunday, I may not have enough history to give me meaningful recommendations.  This is just something to be aware of.</p>
<p>What I'm looking for in this DMV is the number of user_seeks and the est_impact.  Also, if I haven't rebooted my server in a while, I take a look at last_user_seek so I can determine whether or not it's still accurate.  </p>
<p>Next, I take a look at my existing indexes using Kimberly Tripp's <a href="http://www.sqlskills.com/blogs/Kimberly/post/sp_helpindex2-to-show-included-columns-(20052b)-and-filtered-indexes-(2008)-which-are-not-shown-by-sp_helpindex.aspx" target="_blank">sp_helpindex2</a> system stored proc.  I use her proc instead of sp_helpindex because I need to see included columns.  </p>
<p>If you're wondering why I'm looking at existing indexes, the reason is because I'm looking for indexes that can be modified <em>slightly</em> to accommodate my missing index needs.  By "modified slightly," I mean that I'd only want to make a change to an existing index if it did not drastically change the size or composition of an index, i.e. adding one or two narrow columns as included columns.  I do NOT mean making changes that double the size of your index; in those cases, you'd probably be better off creating a brand new index.  </p>
<p>Looking at existing indexes is actually a pretty critical part of the puzzle.  If I have a proc that only gets called a few times an hour and could benefit from a better index, I may not create that index if it means adding a wide, expensive index to a busy table.  If I can make a small modification to an existing index, then there's a greater chance I'll make the change and cover my query.</p>
<p>At this point, I should have enough information to start making decisions.  I was going to write out the path I normally take when making decisions, but I thought, "Hey!  What a great time for a diagram."  So here you go:</p>
<div id="attachment_873" class="wp-caption alignnone" style="width: 219px"><a href="http://sqlfool.com/wp-content/uploads/2009/04/20090428_tree.jpg" target="_blank"><img src="http://sqlfool.com/wp-content/uploads/2009/04/20090428_tree-209x300.jpg" alt="Decision Path" title="20090428_tree" width="209" height="300" class="size-medium wp-image-873" /></a><p class="wp-caption-text">Decision Path</p></div>
<p><em><strong>Disclaimer:</strong>  I'm *not* a Visio wizard, so if I butchered the use of certain symbols in my diagram, please let me know so I can a) fix it, and b) learn from it!</em></p>
<p>It's hard to really put all of the decision paths into a single, small diagram like this.  There's a lot of variables that I'm not even touching here.  But I think this is a fairly good "generic" representation of the path I take.  When I hit an "end" process, it means I don't create the missing index at this time.  Maybe in the future, it'll become necessary, but I prefer to err on the side of less indexes.  </p>
<p>So there you have it, a brief look at my missing index process.  Hopefully someone finds it helpful.  <img src='http://sqlfool.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://sqlfool.com/2009/04/a-look-at-missing-indexes/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Find Missing Indexes in Stored Procs with T-SQL</title>
		<link>http://sqlfool.com/2009/03/find-missing-indexes/</link>
		<comments>http://sqlfool.com/2009/03/find-missing-indexes/#comments</comments>
		<pubDate>Mon, 02 Mar 2009 16:11:37 +0000</pubDate>
		<dc:creator>Michelle Ufford</dc:creator>
				<category><![CDATA[Performance & Tuning]]></category>
		<category><![CDATA[SQL Tips]]></category>
		<category><![CDATA[Syndication]]></category>
		<category><![CDATA[T-SQL Scripts]]></category>
		<category><![CDATA[indexes]]></category>
		<category><![CDATA[missing indexes]]></category>
		<category><![CDATA[query plan]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://sqlfool.com/?p=572</guid>
		<description><![CDATA[This post should probably be called "The Power of Twitter." I've said it before, I'll say it again: I love Twitter. I mostly follow SQL Server people, so it's become a great source of new information and help when I feel like banging my head against the wall when I get stumped. So last week, [...]]]></description>
			<content:encoded><![CDATA[<p>This post should probably be called "The Power of Twitter."  I've said it before, I'll say it again: I love Twitter.  I mostly follow SQL Server people, so it's become a great source of new information and help <span style="text-decoration: line-through;">when I feel like banging my head against the wall</span> when I get stumped.</p>
<p>So last week, <a href="http://sqlblog.com/blogs/jonathan_kehayias" target="_blank">Jonathan Kehayias</a> (<a href="http://twitter.com/jmkehayias" target="_blank">@jmkehayias</a>) posted a link to a <a href="http://social.msdn.microsoft.com/Forums/en-US/sqldatabaseengine/thread/71814032-cd8d-4802-80de-7fb2bee80f41" target="_blank">missing index script</a> on the MSDN forums.  Jonathan's script is modified from something he put together for a question posed by <a href="http://facility9.com" target="_blank">Jeremiah Peschka</a> (<a href="http://twitter.com/peschkaj" target="_blank">@peschkaj</a>).  </p>
<p>Jonathan's script intrigued me.  I'd never tried to search a query plan's XML before, and it certainly presents some interesting possibilities.  After dealing with a missing index in production a few weeks ago (caused by an index change), I thought it'd be a great idea to put a regular monitor in place.  </p>
<p>Everything was going well until I ran into a problem where I couldn't get the proc name returned.  The results spanned numerous databases; I had the object_id and database_id, but I wanted to store the proc name instead.  I tried several different methods, including sp_msforeachdb and sp_executeSQL, and while I had a working solution, it was a little more clunky than I liked.  So I asked my awesome followers on Twitter for any tips and within minutes I had half a dozen responses.  In the end, <a href="http://twitter.com/MladenPrajdic" target="_blank">@MladenPrajdic</a> solved my problem with a pretty simple solution: put 'Use ?;' at the start of my sp_msforeachdb statement.  Thanks again, Mladen!</p>
<p>I've now had this process running on my server for a few days now, with good success.  The stored procedure below will return the database name, proc name, and query plan XML for any stored proc with a missing index.  This is a centralized proc that will store the results in a table for later action.  If you click on the XML, you should see the actual query plan with the missing index details.  Because this looks at cached query plans, your best bet is to run it fairly regularly (maybe daily) to increase your chances of catching any problem procs.</p>

<div class="wp_syntax"><div class="code"><pre class="tsql" style="font-family:monospace;"><span style="color: #008080;">/* Create a stored procedure skeleton */</span>
<span style="color: #0000FF;">If</span> <span style="color: #FF00FF;">ObjectProperty</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">Object_ID</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'dbo.dba_missingIndexStoredProc_sp'</span><span style="color: #808080;">&#41;</span>, N<span style="color: #FF0000;">'IsProcedure'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">Is</span> Null
<span style="color: #0000FF;">Begin</span>
    <span style="color: #0000FF;">Execute</span> <span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'Create Procedure dbo.dba_missingIndexStoredProc_sp As Print '</span><span style="color: #FF0000;">'Hello World!'</span><span style="color: #FF0000;">''</span><span style="color: #808080;">&#41;</span>
    <span style="color: #0000FF;">RaisError</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'Procedure dba_missingIndexStoredProc_sp created.'</span>, <span style="color: #000;">10</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span>;
<span style="color: #0000FF;">End</span>;
Go
&nbsp;
<span style="color: #008080;">/* Drop our table if it already exists */</span>
<span style="color: #0000FF;">If</span> Exists<span style="color: #808080;">&#40;</span><span style="color: #0000FF;">Select</span> <span style="color: #FF00FF;">Object_ID</span> <span style="color: #0000FF;">From</span> sys.<span style="color: #202020;">tables</span> <span style="color: #0000FF;">Where</span> <span style="color: #808080;">&#91;</span>name<span style="color: #808080;">&#93;</span> <span style="color: #808080;">=</span> N<span style="color: #FF0000;">'dba_missingIndexStoredProc'</span><span style="color: #808080;">&#41;</span>
<span style="color: #0000FF;">Begin</span>
    <span style="color: #0000FF;">Drop</span> <span style="color: #0000FF;">Table</span> dbo.<span style="color: #202020;">dba_missingIndexStoredProc</span>
    <span style="color: #0000FF;">Print</span> <span style="color: #FF0000;">'dba_missingIndexStoredProc table dropped!'</span>;
<span style="color: #0000FF;">End</span>
&nbsp;
<span style="color: #008080;">/* Create our table */</span>
<span style="color: #0000FF;">Create</span> <span style="color: #0000FF;">Table</span> dbo.<span style="color: #202020;">dba_missingIndexStoredProc</span>
<span style="color: #808080;">&#40;</span>
      missingIndexSP_id <span style="color: #0000FF;">int</span> <span style="color: #0000FF;">Identity</span><span style="color: #808080;">&#40;</span><span style="color: #000;">1</span>,<span style="color: #000;">1</span><span style="color: #808080;">&#41;</span>   Not Null
    , databaseName      <span style="color: #0000FF;">varchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">128</span><span style="color: #808080;">&#41;</span>        Not Null
    , databaseID        <span style="color: #0000FF;">int</span>                 Not Null
    , objectName        <span style="color: #0000FF;">varchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">128</span><span style="color: #808080;">&#41;</span>        Not Null
    , objectID          <span style="color: #0000FF;">int</span>                 Not Null
    , query_plan        xml                 Not Null
    , executionDate     <span style="color: #0000FF;">smalldatetime</span>       Not Null
&nbsp;
    <span style="color: #0000FF;">Constraint</span> PK_missingIndexStoredProc
        <span style="color: #0000FF;">Primary</span> <span style="color: #0000FF;">Key</span> <span style="color: #0000FF;">Clustered</span><span style="color: #808080;">&#40;</span>missingIndexSP_id<span style="color: #808080;">&#41;</span>
<span style="color: #808080;">&#41;</span>;
&nbsp;
<span style="color: #0000FF;">Print</span> <span style="color: #FF0000;">'dba_missingIndexStoredProc Table Created'</span>;
&nbsp;
<span style="color: #008080;">/* Configure our settings */</span>
<span style="color: #0000FF;">Set</span> ANSI_Nulls <span style="color: #0000FF;">On</span>;
<span style="color: #0000FF;">Set</span> Quoted_Identifier <span style="color: #0000FF;">On</span>;
Go
&nbsp;
<span style="color: #0000FF;">Alter</span> <span style="color: #0000FF;">Procedure</span> dbo.<span style="color: #202020;">dba_missingIndexStoredProc_sp</span>
&nbsp;
        <span style="color: #008080;">/* Declare Parameters */</span>
            @lastExecuted_inDays    <span style="color: #0000FF;">int</span> <span style="color: #808080;">=</span> <span style="color: #000;">7</span>
          , @minExecutionCount      <span style="color: #0000FF;">int</span> <span style="color: #808080;">=</span> <span style="color: #000;">7</span>
          , @logResults             <span style="color: #0000FF;">bit</span> <span style="color: #808080;">=</span> <span style="color: #000;">1</span>
          , @displayResults         <span style="color: #0000FF;">bit</span> <span style="color: #808080;">=</span> <span style="color: #000;">0</span>
&nbsp;
<span style="color: #0000FF;">As</span>
<span style="color: #008080;">/*********************************************************************************
    Name:       dba_missingIndexStoredProc_sp
&nbsp;
    Author:     Michelle Ufford, http://sqlfool.com
&nbsp;
    Purpose:    Retrieves stored procedures with missing indexes in their
                cached query plans.
&nbsp;
                @lastExecuted_inDays = number of days old the cached query plan
                                       can be to still appear in the results;
                                       the HIGHER the number, the longer the
                                       execution time.
&nbsp;
                @minExecutionCount = minimum number of executions the cached
                                     query plan can have to still appear 
                                     in the results; the LOWER the number,
                                     the longer the execution time.
&nbsp;
                @logResults = store results in dba_missingIndexStoredProc
&nbsp;
                @displayResults = return results to the caller
&nbsp;
    Notes:      This is not 100% guaranteed to catch all missing indexes in
                a stored procedure.  It will only catch it if the stored proc's
                query plan is still in cache.  Run regularly to help minimize
                the chance of missing a proc.
&nbsp;
    Called by:  DBA and/or SQL Agent Job
&nbsp;
    Date        User    Description
    ----------------------------------------------------------------------------
    2009-03-02  MFU     Initial Release for public consumption
*********************************************************************************
    Exec dbo.dba_missingIndexStoredProc_sp
          @lastExecuted_inDays  = 30
        , @minExecutionCount    = 5
        , @logResults           = 1
        , @displayResults       = 1;
*********************************************************************************/</span>
&nbsp;
<span style="color: #0000FF;">Set</span> <span style="color: #0000FF;">NoCount</span> <span style="color: #0000FF;">On</span>;
<span style="color: #0000FF;">Set</span> XACT_Abort <span style="color: #0000FF;">On</span>;
<span style="color: #0000FF;">Set</span> Ansi_Padding <span style="color: #0000FF;">On</span>;
<span style="color: #0000FF;">Set</span> Ansi_Warnings <span style="color: #0000FF;">On</span>;
<span style="color: #0000FF;">Set</span> ArithAbort <span style="color: #0000FF;">On</span>;
<span style="color: #0000FF;">Set</span> Concat_Null_Yields_Null <span style="color: #0000FF;">On</span>;
<span style="color: #0000FF;">Set</span> Numeric_RoundAbort <span style="color: #0000FF;">Off</span>;
&nbsp;
<span style="color: #0000FF;">Begin</span>
&nbsp;
    <span style="color: #008080;">/* Declare Variables */</span>
    <span style="color: #0000FF;">Declare</span> @currentDateTime <span style="color: #0000FF;">smalldatetime</span>;
&nbsp;
    <span style="color: #0000FF;">Set</span> @currentDateTime <span style="color: #808080;">=</span> <span style="color: #FF00FF;">GetDate</span><span style="color: #808080;">&#40;</span><span style="color: #808080;">&#41;</span>;
&nbsp;
    <span style="color: #0000FF;">Declare</span> @plan_handles <span style="color: #0000FF;">Table</span>
    <span style="color: #808080;">&#40;</span>
        plan_handle     <span style="color: #0000FF;">varbinary</span><span style="color: #808080;">&#40;</span><span style="color: #000;">64</span><span style="color: #808080;">&#41;</span>   Not Null
    <span style="color: #808080;">&#41;</span>;
&nbsp;
    <span style="color: #0000FF;">Create</span> <span style="color: #0000FF;">Table</span> #missingIndexes
    <span style="color: #808080;">&#40;</span>
          databaseID    <span style="color: #0000FF;">int</span>             Not Null
        , objectID      <span style="color: #0000FF;">int</span>             Not Null
        , query_plan    xml             Not Null
&nbsp;
        <span style="color: #0000FF;">Constraint</span> PK_temp_missingIndexes <span style="color: #0000FF;">Primary</span> <span style="color: #0000FF;">Key</span> <span style="color: #0000FF;">Clustered</span>
        <span style="color: #808080;">&#40;</span>
            databaseID, objectID
        <span style="color: #808080;">&#41;</span>
    <span style="color: #808080;">&#41;</span>;
&nbsp;
    <span style="color: #0000FF;">Begin</span> Try
&nbsp;
        <span style="color: #008080;">/* Perform some data validation */</span>
        <span style="color: #0000FF;">If</span> @logResults <span style="color: #808080;">=</span> <span style="color: #000;">0</span> And @displayResults <span style="color: #808080;">=</span> <span style="color: #000;">0</span>
        <span style="color: #0000FF;">Begin</span>
&nbsp;
            <span style="color: #008080;">/* Log the fact that there were open transactions */</span>
            <span style="color: #0000FF;">Execute</span> dbo.<span style="color: #202020;">dba_logError_sp</span>
                  @errorType            <span style="color: #808080;">=</span> <span style="color: #FF0000;">'app'</span>
                , @app_errorProcedure   <span style="color: #808080;">=</span> <span style="color: #FF0000;">'dba_missingIndexStoredProc_sp'</span>
                , @app_errorMessage     <span style="color: #808080;">=</span> <span style="color: #FF0000;">'@logResults = 0 and @displayResults = 0; no action taken, exiting stored proc.'</span>
                , @forceExit            <span style="color: #808080;">=</span> <span style="color: #000;">1</span>
                , @returnError          <span style="color: #808080;">=</span> <span style="color: #000;">1</span>;  
&nbsp;
        <span style="color: #0000FF;">End</span>;
&nbsp;
        <span style="color: #0000FF;">Begin</span> <span style="color: #0000FF;">Transaction</span>;
&nbsp;
        <span style="color: #008080;">/* Retrieve distinct plan handles to minimize dm_exec_query_plan lookups */</span>
        <span style="color: #0000FF;">Insert</span> <span style="color: #0000FF;">Into</span> @plan_handles
        <span style="color: #0000FF;">Select</span> <span style="color: #0000FF;">Distinct</span> plan_handle
        <span style="color: #0000FF;">From</span> sys.<span style="color: #202020;">dm_exec_query_stats</span>
        <span style="color: #0000FF;">Where</span> last_execution_time <span style="color: #808080;">&gt;</span> <span style="color: #FF00FF;">DateAdd</span><span style="color: #808080;">&#40;</span><span style="color: #0000FF;">day</span>, <span style="color: #808080;">-</span>@lastExecuted_inDays, @currentDateTime<span style="color: #808080;">&#41;</span>
            And execution_count <span style="color: #808080;">&gt;</span> @minExecutionCount;
&nbsp;
        <span style="color: #0000FF;">With</span> xmlNameSpaces <span style="color: #808080;">&#40;</span>
            <span style="color: #0000FF;">Default</span> <span style="color: #FF0000;">'http://schemas.microsoft.com/sqlserver/2004/07/showplan'</span>
        <span style="color: #808080;">&#41;</span>
&nbsp;
        <span style="color: #008080;">/* Retrieve our query plan's XML if there's a missing index */</span>
        <span style="color: #0000FF;">Insert</span> <span style="color: #0000FF;">Into</span> #missingIndexes
        <span style="color: #0000FF;">Select</span> deqp.<span style="color: #808080;">&#91;</span>dbid<span style="color: #808080;">&#93;</span>
            , deqp.<span style="color: #202020;">objectid</span>
            , deqp.<span style="color: #202020;">query_plan</span> 
        <span style="color: #0000FF;">From</span> @plan_handles <span style="color: #0000FF;">As</span> ph
        Cross Apply sys.<span style="color: #202020;">dm_exec_query_plan</span><span style="color: #808080;">&#40;</span>ph.<span style="color: #202020;">plan_handle</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">As</span> deqp 
        <span style="color: #0000FF;">Where</span> deqp.<span style="color: #202020;">query_plan</span>.<span style="color: #202020;">exist</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'//MissingIndex'</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">=</span> <span style="color: #000;">1</span>
            And deqp.<span style="color: #202020;">objectid</span> <span style="color: #0000FF;">Is</span> Not Null;
&nbsp;
        <span style="color: #008080;">/* Do we want to store the results of our process? */</span>
        <span style="color: #0000FF;">If</span> @logResults <span style="color: #808080;">=</span> <span style="color: #000;">1</span>
        <span style="color: #0000FF;">Begin</span>
            <span style="color: #0000FF;">Insert</span> <span style="color: #0000FF;">Into</span> dbo.<span style="color: #202020;">dba_missingIndexStoredProc</span>
            <span style="color: #0000FF;">Execute</span> sp_msForEachDB <span style="color: #FF0000;">'Use ?; 
                                    Select '</span><span style="color: #FF0000;">'?'</span><span style="color: #FF0000;">'
                                        , mi.databaseID
                                        , Object_Name(o.object_id)
                                        , o.object_id
                                        , mi.query_plan
                                        , GetDate()
                                    From sys.objects As o 
                                    Join #missingIndexes As mi 
                                        On o.object_id = mi.objectID 
                                    Where databaseID = DB_ID();'</span>;
&nbsp;
        <span style="color: #0000FF;">End</span>
        <span style="color: #008080;">/* We're not logging it, so let's display it */</span>
        <span style="color: #0000FF;">Else</span>
        <span style="color: #0000FF;">Begin</span>
            <span style="color: #0000FF;">Execute</span> sp_msForEachDB <span style="color: #FF0000;">'Use ?; 
                                    Select '</span><span style="color: #FF0000;">'?'</span><span style="color: #FF0000;">'
                                        , mi.databaseID
                                        , Object_Name(o.object_id)
                                        , o.object_id
                                        , mi.query_plan
                                        , GetDate()
                                    From sys.objects As o 
                                    Join #missingIndexes As mi 
                                        On o.object_id = mi.objectID 
                                    Where databaseID = DB_ID();'</span>;
        <span style="color: #0000FF;">End</span>;
&nbsp;
        <span style="color: #008080;">/* See above; this part will only work if we've 
           logged our data. */</span>
        <span style="color: #0000FF;">If</span> @displayResults <span style="color: #808080;">=</span> <span style="color: #000;">1</span> And @logResults <span style="color: #808080;">=</span> <span style="color: #000;">1</span>
        <span style="color: #0000FF;">Begin</span>
            <span style="color: #0000FF;">Select</span> <span style="color: #808080;">*</span>
            <span style="color: #0000FF;">From</span> dbo.<span style="color: #202020;">dba_missingIndexStoredProc</span>
            <span style="color: #0000FF;">Where</span> executionDate <span style="color: #808080;">&gt;=</span> @currentDateTime;
        <span style="color: #0000FF;">End</span>;
&nbsp;
        <span style="color: #008080;">/* If you have an open transaction, commit it */</span>
        <span style="color: #0000FF;">If</span> <span style="color: #FF00FF;">@@TranCount</span> <span style="color: #808080;">&gt;</span> <span style="color: #000;">0</span>
            <span style="color: #0000FF;">Commit</span> <span style="color: #0000FF;">Transaction</span>;
&nbsp;
    <span style="color: #0000FF;">End</span> Try
    <span style="color: #0000FF;">Begin</span> Catch
&nbsp;
        <span style="color: #008080;">/* Whoops, there was an error... rollback! */</span>
        <span style="color: #0000FF;">If</span> <span style="color: #FF00FF;">@@TranCount</span> <span style="color: #808080;">&gt;</span> <span style="color: #000;">0</span>
            <span style="color: #0000FF;">Rollback</span> <span style="color: #0000FF;">Transaction</span>;
&nbsp;
        <span style="color: #008080;">/* Return an error message and log it */</span>
        <span style="color: #0000FF;">Execute</span> dbo.<span style="color: #202020;">dba_logError_sp</span>;
&nbsp;
    <span style="color: #0000FF;">End</span> Catch;
&nbsp;
    <span style="color: #008080;">/* Clean-Up! */</span>
    <span style="color: #0000FF;">Drop</span> <span style="color: #0000FF;">Table</span> #missingIndexes;
&nbsp;
    <span style="color: #0000FF;">Set</span> <span style="color: #0000FF;">NoCount</span> <span style="color: #0000FF;">Off</span>;
    <span style="color: #0000FF;">Return</span> <span style="color: #000;">0</span>;
<span style="color: #0000FF;">End</span>
Go</pre></div></div>

<p>Not know what "EXECUTE dbo.dba_logError_sp;" is doing?  Check out my blog post on <a href="http://sqlfool.com/2008/12/error-handling-in-t-sql/">Error Handling in T-SQL</a>.</p>
<p>HTH!</p>
<p>Michelle</p>
<p>Source: <a href="http://sqlfool.com/2009/03/find-missing-indexes/">http://sqlfool.com/2009/03/find-missing-indexes/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://sqlfool.com/2009/03/find-missing-indexes/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>

