需要帮助优化存储过程

时间:2015-02-26 04:54:40

标签: sql-server tsql stored-procedures

最近开始在一家公司工作,发现了一个正在爬行的存储过程。目前在这里工作的人都不知道如何优化它,但它对我来说看起来很有趣。想知道是否有人看到任何明显的事情:

--------- [Debug Block] ------------
SET @DebugMessage = 'Execution Started'

EXEC [dbo].[MarkInProcessDebugPoint] 
     @ProcId = @@PROCID
    ,@DebugType = 0
    ,@Message = @DebugMessage
--------- [Debug Block] ------------

BEGIN TRY

DECLARE @tbl_Downloads  as TABLE (
    Revision bigint,
    AssignedStores varchar (max),
    Id varchar (64),
    DownloadId int
)

-- Get Id, and legacy Id
INSERT @tbl_Downloads (Revision, DownloadId, Id)
   SELECT 
      isnull(DCG.[DOWNLOAD_ID], 0), [Value], 
      isnull(DCG.[GUID], newid())
   FROM 
      dbo.fn_Valid_Split(@Downloads, ';') AS CD 
   LEFT JOIN
      [DIGITAL_CONTENT_GUID] DCG ON CD.Value = DCG.[DOWNLOAD_ID]

INSERT [DIGITAL_CONTENT_GUID]
   SELECT 
      DownloadId, 1, max(Id)
   FROM 
      @tbl_Downloads
   WHERE 
      Revision = 0 and DownloadId > 0
   GROUP BY 
      DownloadId    

-- Create track GUID values if the album is in the list
INSERT [DIGITAL_CONTENT_GUID] (DOWNLOAD_ID, CONTENT_TYPE_ID, [GUID]) 
   SELECT 
      A.DOWNLOAD_ID, 1, NEWID()
   FROM
      (SELECT DISTINCT 
          P.DOWNLOAD_ID
       FROM 
          DOWNLOAD_PACK P (NOLOCK)
       INNER JOIN
          @tbl_Downloads T ON P.DOWNLOAD_PACK_ID = T.DownloadId
       WHERE 
          NOT EXISTS (SELECT 1 
                      FROM [DIGITAL_CONTENT_GUID] G (nolock) 
                      WHERE G.DOWNLOAD_ID = P.DOWNLOAD_ID)
      ) A

--------- [Debug Block] ------------
SELECT @DebugMessage = 'Get Id, and legacy Id' 

EXEC [dbo].[MarkInProcessDebugPoint] 
     @ProcId = @@PROCID
    ,@DebugType = 0
    ,@Message = @DebugMessage
--------- [Debug Block] ------------

SELECT 
    --TA.Revision, 
    [dbo].[Fn_ContentExport_GetAssignedStores_Json]  (TA.DownloadId, 1) AS AssignedStores,
    TA.Id, 
    TA.DownloadId As LegacyId, 
    [dbo].[Fn_ContentExport_GetContentNameSpace]  (CD.Download_Type_Id) AS [Namespace],
    [dbo].[Fn_ContentExport_GetContentTypeName]  (CD.Download_Type_Id) AS [Type],
    T.TITLE AS Title,
    T.DISPLAY_ARTIST_NAME AS Subtitle,
    CD.DESCRIPTION AS [Description],
    [dbo].[Fn_ContentExport_GetContentArtworks]  (TA.DownloadId, CD.Download_Type_Id, 0) AS Artwork,
    [dbo].[Fn_ContentExport_GetTitleArtists_Json]  (CD.TITLE_ID, 0) AS Artists,
    [dbo].[Fn_ContentExport_GetContentTypeData]  (TA.DownloadId, CD.Download_Type_Id, 2240) AS TypeEntity,
    '' AS PublicTags,
    [dbo].[Fn_ContentExport_GetInternalTags_Json] (CD.Global_Content_Id) AS InternalTags,
    CD.SUPPLIER_ID AS SupplierId,
    S.NAME AS SupplierName,
    CD.RELEASE_DATE AS [ReleaseDateTime2],
    CD.VALID_TO_DATE As [ExpiryDateTime2],
    CASE
         WHEN CD.IS_DELETED = 1 THEN 1 
         WHEN CD.IS_DELETED = 0 AND [dbo].[Fn_ContentExport_GetContentIsSearchable] (TA.DownloadId) = 0 THEN 1
         ELSE 0
    END As Archived,

    CD.DATE_CREATED AS CreationDateTime,
    CD.DATE_MODIFIED AS ModifiedDateTime,
    [dbo].[Fn_ContentExport_GetContentTierPriceId]  (CD.Download_Type_Id, TA.DownloadId) As [PricingTierId],
    CD.TITLE_ID As [LegacyTitleId]
    -- [dbo].[Fn_ContentExport_GetContentIsSearchable]  (TA.DownloadId) AS IsSearchable
FROM 
    @tbl_Downloads AS TA
INNER JOIN
    CONTENT_DOWNLOAD CD (NOLOCK) ON TA.DownloadId = CD.DOWNLOAD_ID
INNER JOIN
    TITLE T (NOLOCK) ON T.TITLE_ID = CD.TITLE_ID
INNER JOIN
    SUPPLIER S (NOLOCK) ON CD.SUPPLIER_ID = s.SUPPLIER_ID
WHERE
    CD.DOWNLOAD_TYPE_ID <> 125

END TRY
BEGIN CATCH
    -- Use RAISERROR inside the CATCH block to return error
    -- information about the original error that caused
    -- execution to jump to the CATCH block.
    DECLARE @ErrorMessage NVARCHAR(2048);
    DECLARE @ErrorSeverity INT;
    DECLARE @ErrorState INT;

    SELECT 
        @ErrorMessage = ERROR_MESSAGE(),
        @ErrorSeverity = ERROR_SEVERITY(),
        @ErrorState = ERROR_STATE();

    --------- [Debug Block] ------------
    SET @DebugMessage = CAST(@ErrorSeverity AS VARCHAR(100)) + ':' +        CAST(@ErrorState AS VARCHAR(100)) + ':' + @ErrorMessage

    EXEC [dbo].[MarkInProcessDebugPoint] 
         @ProcId = @@PROCID
        ,@DebugType = 1
        ,@Message = @DebugMessage
    --------- [Debug Block] ------------

    RAISERROR (@ErrorMessage, -- Message text.
               @ErrorSeverity, -- Severity.
               @ErrorState -- State.
               );

      END CATCH

非常感谢

1 个答案:

答案 0 :(得分:1)

缺少fn_Valid_Split和@Downloads的内容,所以假设在分隔列表中有几个项目(10-20或类似的东西)。

我会检查几件事:

  • 从计划缓存中检查这些语句中的哪一个实际上是导致问题的语句(高I / O,高CPU时间)。您还应该检查查询返回的内容&#34; set statistics io&#34;是的。统计I / O不会显示函数中的I / O,因此您也需要计划缓存。如果所有连接的表都具有适当的连接索引,则至少也要查看最后一个选择。

  • 绝对查看上次选择中的用户定义函数。摆脱它们是好的,如果没有,检查是否可以将它们更改为内联表值函数。

  • 如果调用fn_Valid_Split超过它应该调用的数量(例如,每次执行多次),则将其从连接中取出并用它返回的内容填充临时表(或表变量)。您还应该检查Jeff Moden的DelimitedSplit8k,以防您的实施情况不佳:http://www.sqlservercentral.com/articles/Tally+Table/72993/

  • 如果@tbl_Downloads中有很多行尝试将其更改为临时表,那么它将包含统计信息。当它是临时表时,您还可以将(clustered?)索引添加到DownloadId。这可能有助于加入。

  • 我也肯定会建议删除nolock。它可能比它修复的东西更令人头疼。#34;如果存在阻止,我会尝试正确修复它。