聚簇和非聚簇索引寻求增加存​​储过程中的执行时间

时间:2016-07-10 14:37:29

标签: sql sql-server stored-procedures indexing execution-time

我有一个存储过程需要3分钟才能执行,当我显示我找到的执行计划时

  

聚簇索引搜索和非聚簇索引搜索

index seeking

clustered index seek

我的查询:

SELECT distinct
    [tbl_worflowprocess].[currenttid]
    ,USR2.[firstname] AS [prev_action_user_name]
    ,USR3.[firstname] AS [current_action_user_name]
    ,COD2.[Code] AS [reasontext]
    ,[tbl_application_details].[application_id] AS [ApplicationId]
    ,[tbl_application_details].[application_number] AS [ApplicationNumber]
    ,[dbo].[fn_app_GetApplicationId]([tbl_application_details].[link_application_id]) AS [LinkApplicationId]
    ,[tbl_application_details].[link_type] AS [LinkType]
    ,[dbo].[fn_app_CountProductsInApplication]([tbl_application_details].[application_id]) AS [ProductsCount]
    ,[tbl_application_details].[submission_date] AS [SubmissionDate]
    ,[tbl_jurisdiction].[jurisdictionname]
    ,[tbl_devicetype].[devicetype]
    ,COD1.[Code] AS [ClassificationName]
    ,EST1.[name] AS [ApplicantName]
    ,EST2.[name] AS [ManufacturerName]
    ,[dbo].[fnGetApplicationStatusFromTaskId]([tbl_worflowprocess].[currenttid]) AS [AppStatus]
    ,[dbo].[fnGetApplicationStatusText](@pLoggedInUserRoleId,[tbl_worflowprocess].[currenttid]) AS [StatusText]
    ,[Paid] = (CASE [tbl_application_details].[paid] WHEN 1 THEN 'Yes' ELSE 'No' END)
    ,[CreationDate] = [tbl_worflowprocess].[creationdate]
    ,[CommentText] = 
                    (select CommentText 
                        from dbo.tbl_application_comments
                            where Id = (select max(Id) from dbo.tbl_application_comments
                                        where ApplicationId= [tbl_application_details].[application_id] and UserId = @pLoggedInUserID ))
    ,[LastCab] = (select isnull(dbo.fnGetLastCabForApplication([tbl_application_details].[application_id]),'-'))
    ,[tbl_application_details].[ArExpired]

FROM 
    [tbl_worflowprocess]
INNER JOIN
    (SELECT 
         [application_id], [actionbyuser_id],
         [actionbyrole_id], [reason_id], createddate 
     FROM 
         [tbl_applicationworkflowhistory]
     INNER JOIN
         (SELECT 
              [application_id] AS C1, MAX([version]) AS C2
          FROM 
              [tbl_applicationworkflowhistory]
          WHERE 
              (@pCurrentRoleId IS NULL 
               OR [application_id] IN (SELECT [application_id] 
                                       FROM [tbl_applicationworkflowhistory] 
                                       INNER JOIN [tbl_worflowprocess] ON [tbl_applicationworkflowhistory].[application_id] = [tbl_worflowprocess].[applicationid]
                                       WHERE 
                                           (@pSearchInHistory = 0 OR [tbl_applicationworkflowhistory].[actionbyrole_id] = @pCurrentRoleId OR [tbl_worflowprocess].[currentroleid] = @pCurrentRoleId)
                                        AND (@pSearchInHistory = 1 OR [tbl_worflowprocess].[currentroleid] = @pCurrentRoleId)
                                      )
                ) AND
                (@pCurrentUserId IS NULL OR [application_id] IN (
                                    SELECT [application_id] 
                                    FROM [tbl_applicationworkflowhistory] 
                                    INNER JOIN [tbl_worflowprocess] ON [tbl_applicationworkflowhistory].[application_id]=[tbl_worflowprocess].[applicationid]
                                    WHERE 
                                    (@pSearchInHistory=0 OR [tbl_applicationworkflowhistory].[actionbyuser_id] =@pCurrentUserId OR [tbl_worflowprocess].[currentuserid]=@pCurrentUserId)
                                        AND (@pSearchInHistory=1 OR [tbl_worflowprocess].[currentuserid]=@pCurrentUserId)
                                    )
                ) AND
                (@pCurrentEstablishmentId IS NULL OR [application_id] IN (
                                    SELECT [application_id] 
                                    FROM [tbl_applicationworkflowhistory] 
                                    INNER JOIN [tbl_worflowprocess] ON [tbl_applicationworkflowhistory].[application_id]=[tbl_worflowprocess].[applicationid]
                                    WHERE 
                                    (@pSearchInHistory=0 OR [tbl_applicationworkflowhistory].[actionbyuser_id] IN 
                                    (SELECT [user_id] FROM [tbl_user] WHERE [establishment_id]=@pCurrentEstablishmentId) OR [tbl_worflowprocess].[currentuserid] IN 
                                    (SELECT [user_id] FROM [tbl_user] WHERE [establishment_id]=@pCurrentEstablishmentId))
                                        AND (@pSearchInHistory=1 OR [tbl_worflowprocess].[currentuserid] IN 
                                        (SELECT [user_id] FROM [tbl_user] WHERE [establishment_id]=@pCurrentEstablishmentId))
                                    )
                )
        GROUP BY [application_id]
    )AS T1 ON ([tbl_applicationworkflowhistory].[application_id]=T1.C1 AND [tbl_applicationworkflowhistory].[version]=T1.C2)
) AS T2 ON([tbl_worflowprocess].[applicationid]=T2.[application_id])
INNER JOIN [tbl_application_details] ON [tbl_application_details].[application_id]=[tbl_worflowprocess].[applicationid]
INNER JOIN [tbl_user] USR1 ON USR1.[user_id]=[tbl_application_details].[responsible_user_id]
INNER JOIN [tbl_establishments] EST1 on EST1.[establishment_id] = USR1.[establishment_id]
LEFT OUTER JOIN [tbl_user] USR2 ON USR2.[user_id]=T2.[actionbyuser_id]
LEFT OUTER JOIN [tbl_user] USR3 ON USR3.[user_id]=[tbl_worflowprocess].[currentuserid]
LEFT OUTER JOIN [tbl_establishments] EST2 on EST2.[establishment_id] = [tbl_application_details].[manufacturer_id]
LEFT OUTER JOIN [tbl_jurisdiction] ON [tbl_jurisdiction].[jurisdiction_id]=[tbl_application_details].[jurisdiction_id]
LEFT OUTER JOIN [tbl_devicetype] ON [tbl_devicetype].[devicetype_id]=[tbl_application_details].[device_type_id]
LEFT OUTER JOIN [tbl_codes] COD1 ON COD1.[code_id]=[tbl_application_details].[device_classification_id]
LEFT OUTER JOIN [tbl_codes] COD2 ON COD2.[code_id]=T2.[reason_id]
LEFT OUTER JOIN [tbl_certificates] CERTF ON CERTF.[application_id]=[tbl_application_details].[application_id]
WHERE
    (@pWFTasks IS NULL OR 
     [tbl_worflowprocess].[currenttid] IN (SELECT item 
                                           FROM [dbo].[fnSplit](@pWFTasks,',')))

有什么方法可以改善我的查询吗?

1 个答案:

答案 0 :(得分:0)

  1. 尝试根据查询在表上创建索引 - 使用建议的性能改进(如果存在)并且不会干扰数据库的其余部分。
    1. 如果您在查询执行计划中有表扫描,而索引已存在于该字段的表上 - 尝试更改索引以包括您选择的列。
    2. 如果可以 - 在查询返回许多结果的情况下避免使用UDF
    3. 如果你可以预先计算 - 使用表变量或CTE执行此操作:例如(如果它返回的值超过1),这可以存储在表变量中:SELECT [user_id] FROM [tbl_user] WHERE [establishment_id ] = @ pCurrentEstablishmentId)
    4. 查询,例如 - "从dbo.tbl_application_comments"中选择最大值(Id) - 可以通过在查询之前使用简单变量来改进
    5. 使用SNAPSHOT或READ UNCOMMITED或至少(nolock)
    6. 确保更新表格的统计信息!
    7. 检查您是否正确使用左连接(vs内连接更快)
    8. 尽可能限制每个连接的行数 - 使用where语句来剪切数据
  2. 更多可以建议,查询优化是一个有趣的领域