Stored procedure with dynamic SQL takes longer to execute than same query executed directly in query analyzer
-
Thursday, January 10, 2013 11:36 AM
I have a stored procedure which builds a sql statement and executes it using 'sp_executesql'. It takes 1 min 53 sec to return around 8000 records. Let’s call it Main procedure.
I wrote temporary stored procedure using the dynamic query generated in main procedure, which also take same time to return same records.
When I directly execute the dynamic query generated in main procedure it took 2 seconds to retrieve same set of records.
Does anyone know why am I getting huge difference in execution time while using stored procedure for same query.
Thanks-Jyoti
All Replies
-
Thursday, January 10, 2013 12:01 PM
Very high level, it must be an issue with parameter sniffing. Can you try giving option recompile to the dynamic query.
Also provide your query.
Please use Marked as Answer if my post solved your problem and use Vote As Helpful if a post was useful.
-
Thursday, January 10, 2013 12:24 PM
ALTER procedure [dbo].[LSAM_Get_Pending_Productionjobs_temp] ( @ProcessId bigINT, @userId bigINT, @superviorsID varchar(20), @roleID tinyint ) as begin --check if requesting user is team cordinator. If yes the get details of TL he is reporting to, to pull reports IF(@roleID = 5) BEGIN SELECT @superviorsID = SupervisorID FROM TBL_User_Role_Process_Map WHERE UserId = @userId and Deleted = 0 SELECT @userId = UserId FROM TBL_Master_User WHERE CognizantID = @superviorsID and Deleted = 0 END --check target configuration DECLARE @TATType tinyint DECLARE @TATField bigint DECLARE @TATFieldName varchar(100) SELECT @TATType = TATType, @TATField = TATFieldID FROM TBL_WorkflowConfiguration WHERE ProcessID = @ProcessID SELECT @TATFieldName = FieldName FROM TBL_DynamicFieldMaster WHERE FieldID = @TATField IF(@TATType IS NOT NULL) BEGIN --do changes from here Declare @JobUploadTable tinyint Select @JobUploadTable = 1--Job upload sheet Declare @JobAllocationTable tinyint Select @JobAllocationTable = 2--Job allocation sheet /*********get table name for job upload data************/ Declare @TableName varchar(200) Select @TableName = TableName from dbo.TBL_MASTER_DYNAMIC_TABLE where processID = @processID AND SheetType = @JobUploadTable --Select @TableName--table name 'JobUpload_12' /*********************End****************************/ /*********get table name for job allocation data************/ Declare @JobAllocationTableName varchar(200) Select @JobAllocationTableName = TableName from dbo.TBL_MASTER_DYNAMIC_TABLE where processID = @processID AND SheetType = @JobAllocationTable --Select @JobAllocationTableName--table name 'JobUpload_12' /*********************End****************************/ declare @col_val_upload nvarchar(4000) set @col_val_upload = '' Select @col_val_upload = @col_val_upload + ',[' + FieldName + ']' from dbo.TBL_DynamicFieldMaster where processid = @ProcessId and sheettype = 1 and deletedstatus = 0 Select @col_val_upload = substring(@col_val_upload,2,len(@col_val_upload)) --Select @col_val_upload if(@col_val_upload <> '')--if column available then only prefix comma select @col_val_upload = ', ' + @col_val_upload --define expected closure time field DECLARE @ExpectedClosureTimeFieldName varchar(100) = 'ExpectedClosureDate' IF(@TATType = 1) BEGIN SELECT @ExpectedClosureTimeFieldName = @TATFieldName END DECLARE @Task VARCHAR(100) Declare @Query nvarchar(4000) Declare @params nvarchar(4000) SELECT @Query = null Select @Query = 'select jobs.JobID,TaskID,splits.task,splits.Priority,Comments,[Current Allocation To],CONVERT(DATETIME, CONVERT(VARCHAR(11),AllocatedOn)) as AllocatedOn,[' + @ExpectedClosureTimeFieldName + '] AS TargetCompletionDate,dbo.ufn_GetHorsMinSecFormat(CASE WHEN (DATEDIFF(s,GETDATE(),ExpectedClosureDate)) < 0 THEN 0 ELSE (DATEDIFF(s,GETDATE(),ExpectedClosureDate)) END) as timeRemain,isnull(statusmaster.JobStatus,''Assignment Pending OR in QC stage'') as JobStatus,TemplateName, SheetName,ExcelFileName' + @col_val_upload + ' from ( select * from UsrLSAutoMetrics.' + quotename(@TableName) + ' where deleted = 0 AND JOBID NOT IN (select JobID from TBL_JobFlowTrack where ProcessID = @ProcessId group by JobID having MAX(ToStatus) in (8,23)))jobs left outer join (select ScheduleID,JobID,TaskID,Comments,allocatedto,AllocatedOn,[Status] from UsrLSAutoMetrics.' + quotename(@JobAllocationTableName) + ' where status in (2,3,5,6) and deleted = 0)jobsAlloc on jobs.JobID = jobsAlloc.JobID left outer join ( SELECT splitid,task,Priority FROM TBL_Master_JobSplit WHERE ProcessID = @ProcessId )splits on jobsAlloc.taskid = splits.splitid left outer join (SELECT TemplateID,TemplateName FROM TBL_Master_Template WHERE DeletedStatus = 0 AND ProcessID = @ProcessId) template ON jobs.TemplateID = template.TemplateID left outer join (select userid, FirstName + '' '' + LastName + ''['' + Cognizantid + '']'' as [Current Allocation To] from tbl_master_user where userid in (select distinct userid from dbo.TBL_User_Role_Process_Map where processid= @ProcessId and deleted = 0))users on jobsAlloc.allocatedto = users.userid LEFT OUTER join ( SELECT JobStatus,JobStatusID FROM TBL_Master_JobStatus )statusmaster on jobsAlloc.[Status] = statusmaster.JobStatusID where AllocatedTo is null or AllocatedTo = @userId or AllocatedTo in (select UserId from TBL_User_Role_Process_Map where Deleted = 0 and SupervisorID = @superviorsID and ProcessId = @ProcessId) order by (DATEDIFF(s,GETDATE(),ExpectedClosureDate))' SELECT @params = N'@ProcessId bigint, ' + N'@userId bigint, ' + N'@superviorsID varchar(20)' --Select @Query EXEC sp_executesql @Query, @params,@ProcessId,@userId,@superviorsID END end
Above is the mail query.
Below is the SQL created dynamically in this procedure:
declare @ProcessId bigint = 49 declare @userId bigint = 187 declare @superviorsID varchar(20) = '144196' select jobs.JobID,TaskID,splits.task,splits.Priority,Comments,[Current Allocation To],CONVERT(DATETIME, CONVERT(VARCHAR(11),AllocatedOn)) as AllocatedOn,[TGT Date - Client submission Date] AS TargetCompletionDate,dbo.ufn_GetHorsMinSecFormat(CASE WHEN (DATEDIFF(s,GETDATE(),ExpectedClosureDate)) < 0 THEN 0 ELSE (DATEDIFF(s,GETDATE(),ExpectedClosureDate)) END) as timeRemain,isnull(statusmaster.JobStatus,'Assignment Pending OR in QC stage') as JobStatus,TemplateName, SheetName,ExcelFileName, [Study ID],[Date of Review],[Patient ID],[eCRF Folder Name],[eCRF Name],[Plan End Date - Internal submission Date],[TGT Date - Client submission Date],[EID] from ( select * from UsrLSAutoMetrics.[JobUpload_49] where deleted = 0 AND JOBID NOT IN (select JobID from TBL_JobFlowTrack where ProcessID = @ProcessId group by JobID having MAX(ToStatus) in (8,23)))jobs left outer join (select ScheduleID,JobID,TaskID,Comments,allocatedto,AllocatedOn,[Status] from UsrLSAutoMetrics.[JobAllocation_49] where status in (2,3,5,6) and deleted = 0)jobsAlloc on jobs.JobID = jobsAlloc.JobID left outer join ( SELECT splitid,task,Priority FROM TBL_Master_JobSplit WHERE ProcessID = @ProcessId )splits on jobsAlloc.taskid = splits.splitid left outer join (SELECT TemplateID,TemplateName FROM TBL_Master_Template WHERE DeletedStatus = 0 AND ProcessID = @ProcessId) template ON jobs.TemplateID = template.TemplateID left outer join (select userid, FirstName + ' ' + LastName + '[' + Cognizantid + ']' as [Current Allocation To] from tbl_master_user where userid in (select distinct userid from dbo.TBL_User_Role_Process_Map where processid= @ProcessId and deleted = 0))users on jobsAlloc.allocatedto = users.userid LEFT OUTER join ( SELECT JobStatus,JobStatusID FROM TBL_Master_JobStatus )statusmaster on jobsAlloc.[Status] = statusmaster.JobStatusID where AllocatedTo is null or AllocatedTo = @userId or AllocatedTo in (select UserId from TBL_User_Role_Process_Map where Deleted = 0 and SupervisorID = @superviorsID and ProcessId = @ProcessId) order by (DATEDIFF(s,GETDATE(),ExpectedClosureDate))
Thanks-Jyoti
-
Thursday, January 10, 2013 12:43 PM
Hi,
Ok so the problem is not with the dynamic sql, it is with in the temp stored procedure which you have created to execute the dynamic sql. You can do following,
1) Comment the exe the line "EXEC sp_executesql @Query, @params,@ProcessId,@userId,@superviorsID " dynamic sql from the main procedure LSAM_Get_Pending_Productionjobs_temp
also keep the Select @Query commented
2) Now try to execute the main query and see how much time it is taking (too see the actual query performance you can use this link (http://insqlserver.com/content/how-check-actual-performance-sql-query)
3) If your main query is taking more time, then comment some select statement in the main query, as I can see there are many select statement you have used, so just try commenting one by one and try executing the query, this way you will figure out which select statement is taking the hit.
You need to fine tune your implementation accordingly
Mark this post as answer if this resolves your issue.
Everything about SQL Server | Experience inside SQL Server -Mohammad Nizamuddin -
Thursday, January 10, 2013 10:59 PM
Permit me to ask one thing: are you able to read that code? I am not. Therefore it is difficult to address your problems.
One important detail is of course, if you ran your two alternatives against the same set of tables.
Even with the same set of tables, you may still get different plans. With dynamic SQL the values are parameters, and SQL Server can sniff these values. With the other query, you have variable, and the optimizer has no informtion at all about their values and make blind assumptions.
Usually, more information gives better plans, but sometimes it backfires. And of course, there may already be a plan for the parameterised query in the cache, but optimized for a different set of parameters.
I have a longer article on my web site that may give you some ideas, or at least understanding of how plans and caches work:
http://www.sommarskog.se/query-plan-mysteries.htmlI were to suggest something out of the blue, I would test what happens if you take out the ORDER BY clause.
Erland Sommarskog, SQL Server MVP, esquel@sommarskog.se- Proposed As Answer by Naomi NMicrosoft Community Contributor, Moderator Friday, January 11, 2013 3:24 AM
- Marked As Answer by Iric WenModerator Friday, January 18, 2013 9:21 AM
-
Friday, January 11, 2013 4:54 AM
Try the below to replace your dynamic statement: I added OPTION(RECOMPILE) to the dynamic SQL.
Select @Query = 'select jobs.JobID,TaskID,splits.task,splits.Priority,Comments,[Current Allocation To],CONVERT(DATETIME, CONVERT(VARCHAR(11),AllocatedOn)) as AllocatedOn,[' + @ExpectedClosureTimeFieldName + '] AS TargetCompletionDate,dbo.ufn_GetHorsMinSecFormat(CASE WHEN (DATEDIFF(s,GETDATE(),ExpectedClosureDate)) < 0 THEN 0 ELSE (DATEDIFF(s,GETDATE(),ExpectedClosureDate)) END) as timeRemain,isnull(statusmaster.JobStatus,''Assignment Pending OR in QC stage'') as JobStatus,TemplateName, SheetName,ExcelFileName' + @col_val_upload + ' from ( select * from UsrLSAutoMetrics.' + quotename(@TableName) + ' where deleted = 0 AND JOBID NOT IN (select JobID from TBL_JobFlowTrack where ProcessID = @ProcessId group by JobID having MAX(ToStatus) in (8,23)))jobs left outer join (select ScheduleID,JobID,TaskID,Comments,allocatedto,AllocatedOn,[Status] from UsrLSAutoMetrics.' + quotename(@JobAllocationTableName) + ' where status in (2,3,5,6) and deleted = 0)jobsAlloc on jobs.JobID = jobsAlloc.JobID left outer join ( SELECT splitid,task,Priority FROM TBL_Master_JobSplit WHERE ProcessID = @ProcessId )splits on jobsAlloc.taskid = splits.splitid left outer join (SELECT TemplateID,TemplateName FROM TBL_Master_Template WHERE DeletedStatus = 0 AND ProcessID = @ProcessId) template ON jobs.TemplateID = template.TemplateID left outer join (select userid, FirstName + '' '' + LastName + ''['' + Cognizantid + '']'' as [Current Allocation To] from tbl_master_user where userid in (select distinct userid from dbo.TBL_User_Role_Process_Map where processid= @ProcessId and deleted = 0))users on jobsAlloc.allocatedto = users.userid LEFT OUTER join ( SELECT JobStatus,JobStatusID FROM TBL_Master_JobStatus )statusmaster on jobsAlloc.[Status] = statusmaster.JobStatusID where AllocatedTo is null or AllocatedTo = @userId or AllocatedTo in (select UserId from TBL_User_Role_Process_Map where Deleted = 0 and SupervisorID = @superviorsID and ProcessId = @ProcessId) order by (DATEDIFF(s,GETDATE(),ExpectedClosureDate)) OPTION(RECOMPILE)'
Please use Marked as Answer if my post solved your problem and use Vote As Helpful if a post was useful.

