最近开始在一家公司工作,发现了一个正在爬行的存储过程。目前在这里工作的人都不知道如何优化它,但它对我来说看起来很有趣。想知道是否有人看到任何明显的事情:
--------- [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
非常感谢
答案 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;如果存在阻止,我会尝试正确修复它。