Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h2>Update #2:</h2> <p>I have one more step to add that ought to make everything clearer. After generating plan information, run the following statement (with the correct plan handle) to look at the ShowPlan XML.</p> <pre><code>DECLARE @val as VARBINARY(64) -- NOTE: Replace the Hex string with the current plan_handle ! SET @val = CONVERT(VARBINARY(64), 0x05001300045A3D02B801BE11000000000000000000000000) SELECT * FROM sys.dm_exec_query_plan(@val) </code></pre> <p>Looking at the generated XML reveals that there are 2 QueryPlan elements, 2 or more StmtSimple/StmtCond elements, and only 1 Batch overall. As <strong>gbn</strong> mentions- there is a difference between "Execution Plans" and "Query Plans". This seems to make it crystal clear what parts we are actually viewing in all the <strong>sys.dm_</strong> queries.</p> <p><a href="http://msdn.microsoft.com/en-us/library/ms189741.aspx" rel="nofollow noreferrer">sys.dm_exec_query_stats at MSDN, SQL 2008</a></p> <p><a href="http://msdn.microsoft.com/en-us/library/ms189747.aspx" rel="nofollow noreferrer">sys.dm_exec_query_plan at MSDN, SQL 2008</a></p> <p>So with all this information, the plan_handle returned is the Execution Plan; and the parts are Query Plan items.</p> <p>--</p> <h2>Update:</h2> <p>After Andrew's comment, I retested and indeed the query plan handles are the same. And, just to be sure- I created a duplicate of the stored procedure, changing only the name, and reran my test against that stored procedure. This also caused a new set of query parts to be generated, that shared the same plan handle. </p> <p>So, <strong>gbn</strong>'s answer appears to be correct, at least with what I've tested here. Interesting stuff.</p> <p>--</p> <p>The latter quote from Gert Drapers appears to be false- here is my test. I'm using SQL 2005 here. In my test, I see 2 query plans generated for different parts of the same stored procedure.</p> <p>First, I created two tables, <strong>tblTag1</strong> and <strong>tblTagWithGUID</strong>. I made them somewhat similar so that my stored procedure can alternate between either table and return results with an identical result table layout.</p> <pre><code>SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO -- Table #1, tblTag1 CREATE TABLE [dbo].[tblTag1]( [id] [int] IDENTITY(1,1) NOT NULL, [createDate] [datetime] NOT NULL CONSTRAINT [DF_tblTag1_createDate] DEFAULT (getdate()), [someTag] [varchar](100) NOT NULL, CONSTRAINT [PK_tblTag1] PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO -- Table #2, tblTagWithGUID CREATE TABLE [dbo].[tblTagWithGUID]( [id] [int] IDENTITY(1,1) NOT NULL, [createDate] [datetime] NOT NULL CONSTRAINT [DF_tblTagWithGUID_createDate] DEFAULT (getdate()), [someTag] [varchar](100) NOT NULL, [someGUID] [uniqueidentifier] NOT NULL CONSTRAINT [DF_tblTagWithGUID_someGUID] DEFAULT (newid()), CONSTRAINT [PK_tblTagWithGUID] PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO </code></pre> <p>Second, the stored procedure. In the stored procedure I select from one or the other table depending on the argument.</p> <pre><code>CREATE PROCEDURE spLoadTags @Pick AS BIT = NULL AS BEGIN IF @Pick = 0 SELECT id, createDate, someTag FROM tblTag1 IF @Pick = 1 SELECT id, createDate, someTag FROM tblTagWithGUID END </code></pre> <p>I added some data to each table- then ran the stored procedure a few dozen times with 0 or 1 as the argument.</p> <p>Next, I ran this query to check up on the generated query plans. I'm sorry if anyone is offended with my sloppiness here- this isn't production code, of course.</p> <pre><code>WITH PlanData AS ( SELECT (SELECT SUBSTRING(text, statement_start_offset/2 + 1, (CASE WHEN statement_end_offset = -1 THEN LEN(CONVERT(nvarchar(MAX),text)) * 2 ELSE statement_end_offset END - statement_start_offset)/2) FROM sys.dm_exec_sql_text(sql_handle) WHERE [text] like '%SELECT id, createDate, someTag FROM tblTag%') AS query_text, plan_handle FROM sys.dm_exec_query_stats ) SELECT DISTINCT execution_count, PlanData.query_text, sys.dm_exec_query_stats.plan_handle FROM sys.dm_exec_query_stats, PlanData WHERE sys.dm_exec_query_stats.plan_handle = PlanData.plan_handle and PlanData.query_text IS NOT NULL ORDER BY execution_count DESC </code></pre> <p>When I run this query, I see a bunch of plans, but because I've run the stored procedure a few dozen times, the distinct parts end up at the top.</p> <pre><code>execution_count query_text plan_handle 96 SELECT id, createDate, someTag FROM tblTag1 0x05001200045A3D02B8613E13000000000000000000000000 96 SELECT id, createDate, someTag FROM tblTagWithGUID 0x05001200045A3D02B8613E13000000000000000000000000 </code></pre> <p>I've only included those two rows, but hopefully this is straightforward enough where someone else can verify my results. You may see other rows if you are using the SQL management tool like I am; presumably caused by browsing tables or other activity.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload