Update # 2:
I have one more step to add, which should make everything clearer. After generating the plan information, run the following statement (with the correct plan descriptor) to view the ShowPlan XML.
DECLARE @val as VARBINARY(64)
Looking at the generated XML, you will find that there are two QueryPlan elements, 2 or more StmtSimple / StmtCond elements, and only 1 package in total. As stated in gbn , there is a difference between “Execution Plans” and “Request Plans”. This seems to clearly show which parts we are actually looking at in all sys.dm _ requests.
sys.dm_exec_query_stats in MSDN, SQL 2008
sys.dm_exec_query_plan in MSDN, SQL 2008
Thus, with all this information, the returned plan_handle is the Execution Plan; and parts are elements of a query plan.
-
Update:
After Andrew commented, I re-tested, and indeed, the query plan handlers match. And to be sure, I duplicated the stored procedure, changing only the name and repeated my test against this stored procedure. It also caused the creation of a new set of query parts that shared the same plan descriptor.
So gbn's answer seems to be correct, at least in what I tested here. Interesting stuff.
-
The last quote from Gert Drapers seems false - here is my test. I am using SQL 2005 here. In my test, I see 2 query plans generated for different parts of the same stored procedure.
First I created two tables: tblTag1 and tblTagWithGUID . I made them somewhat similar so that my stored procedure could alternate between tables and return results with the same layout of the result table.
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
Secondly, the stored procedure. In a stored procedure, I select one or the other table depending on the argument.
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
I added some data to each table, and then ran the stored procedure several dozen times with 0 or 1 as an argument.
Then I ran this query to check the generated query plans. Sorry, if someone is offended by my sloppiness here, of course, this is not a production 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
When I run this query, I see a bunch of plans, but since I started the stored procedure several dozen times, the individual parts end at the top.
execution_count query_text plan_handle 96 SELECT id, createDate, someTag FROM tblTag1 0x05001200045A3D02B8613E13000000000000000000000000 96 SELECT id, createDate, someTag FROM tblTagWithGUID 0x05001200045A3D02B8613E13000000000000000000000000
I have included only these two lines, but hopefully it is simple enough when someone else can check my results. You can see other lines if you use an SQL management tool like me; allegedly caused by viewing tables or other activities.