zoukankan      html  css  js  c++  java
  • SQL Server标量函数改写内联表值函数优化案例

    问题SQL:

    SELECT TOP 1001 ha.HuntApplicationID ,
    ha.PartyNumber ,
    mht.Name AS MasterHuntTypeName ,
    htly.LicenseYear ,
    lStatus.[Status] AS DrawTicketStatus ,
    isnull(dbo.udf_GetHuntApplicationPartyCount(ha.HuntApplicationID), 0) AS MemberCount ,
    count( won.DrawTicketLicenseID) AS DrawnMemberCount ,
    won.drawticketid ,
    dt.PreDrawNonResidentMemberCount AS NRMemberCount ,
    dbo.udf_GetAvgPreferencePoints(dt.DrawTicketID) AS PreferencePointAverage ,
    CASE
    WHEN ha.Quantity > 1 THEN NULL
    ELSE dt.PreDrawRandomNumber
    END AS PreDrawRandomNumber ,
    dsm.Name AS DrawSelectionMethodName ,
    dt.DrawnSequence ,
    dt.PreferencePointRank ,
    dt.DrawID ,
    dt.RandomRank
    FROM dbo.HuntApplication ha
    JOIN dbo.HuntTypeLicenseYear htly ON ha.HuntTypeLicenseYearID = htly.HuntTypeLicenseYearID
    JOIN dbo.MasterHuntType mht ON htly.MasterHuntTypeID = mht.MasterHuntTypeID
    LEFT JOIN dbo.HuntApplicationLicense hal ON ha.HuntApplicationID = hal.HuntApplicationID
    LEFT JOIN dbo.DrawTicket dt ON ha.HuntApplicationID = dt.HuntApplicationID
    LEFT JOIN dbo.DrawTicketLicense won ON dt.DrawTicketID = won.DrawTicketID
    AND won.WasDrawn = 1
    LEFT JOIN dbo.DrawSelectionMethod dsm ON dt.DrawSelectionMethodID = dsm.DrawSelectionMethodID
    LEFT JOIN dbo.StatusCode lStatus ON dt.StatusCodeID = lStatus.StatusCodeID
    JOIN dbo.DrawTicketHuntChoice dthc ON dt.DrawTicketID = dthc.DrawTicketID
    CROSS APPLY dbo.tvf_GetHuntApplicationPartyCount(ha.HuntApplicationID) hapc
    CROSS APPLY dbo.tvf_GetAvgPreferencePoints(dt.DrawTicketID) app
    WHERE 1 = 1
    AND htly.MasterHuntTypeID = @iMasterHuntTypeID
    AND htly.LicenseYear = @iLicenseYear
    AND dt.StatusCodeID = @iDrawTicketStatusCodeID
    AND dthc.WasDrawn = @iHuntChoiceWasDrawn
    GROUP BY ha.HuntApplicationID,
    ha.PartyNumber,
    mht.[Name],
    htly.LicenseYear,
    lStatus.[Status],
    isnull(dbo.udf_GetHuntApplicationPartyCount(ha.HuntApplicationID), 0),
    won.DrawTicketID,
    dt.PreDrawNonResidentMemberCount,
    dbo.udf_GetAvgPreferencePoints(dt.DrawTicketID),
    CASE
    WHEN ha.Quantity > 1 THEN NULL
    ELSE dt.PreDrawRandomNumber
    END,
    dsm.[Name],
    dt.DrawnSequence,
    dt.PreferencePointRank,
    dt.DrawID,
    dt.RandomRank
    ORDER BY htly.LicenseYear DESC,
    mht.Name,
    lStatus.[Status],
    dt.DrawID,
    PreferencePointAverage DESC,
    PreDrawRandomNumber,
    ha.PartyNumber

    静态函数:

    CREATE FUNCTION [dbo].[udf_GetAvgPreferencePoints]
    (@DrawTicketID INT)
    RETURNS NUMERIC (18, 3)
    AS
    BEGIN
    RETURN
    (
    SELECT TOP 1
    CONVERT(DECIMAL, dt.PreDrawPreferencePointTotal) / NULLIF(CONVERT(DECIMAL, dt.PreDrawMemberCount),0)
    FROM dbo.DrawTicket dt
    WHERE dt.DrawTicketID = @DrawTicketID
    )
    END

    执行时间40s

    这是典型可以进行静态函数改写内联表值函数的sql:

    改写后:

    SELECT TOP 1001 ha.HuntApplicationID ,
    ha.PartyNumber ,
    mht.Name AS MasterHuntTypeName ,
    htly.LicenseYear ,
    lStatus.[Status] AS DrawTicketStatus ,
    --isnull(dbo.udf_GetHuntApplicationPartyCount(ha.HuntApplicationID), 0) AS MemberCount ,
    isnull(hapc.MemberCount, 0) AS MemberCount,
    count( won.DrawTicketLicenseID) AS DrawnMemberCount ,
    won.drawticketid ,
    dt.PreDrawNonResidentMemberCount AS NRMemberCount ,
    --dbo.udf_GetAvgPreferencePoints(dt.DrawTicketID) AS PreferencePointAverage ,
    app.PreferencePointAverage PreferencePointAverage,
    CASE
    WHEN ha.Quantity > 1 THEN NULL
    ELSE dt.PreDrawRandomNumber
    END AS PreDrawRandomNumber ,
    dsm.Name AS DrawSelectionMethodName ,
    dt.DrawnSequence ,
    dt.PreferencePointRank ,
    dt.DrawID ,
    dt.RandomRank
    FROM dbo.HuntApplication ha
    JOIN dbo.HuntTypeLicenseYear htly ON ha.HuntTypeLicenseYearID = htly.HuntTypeLicenseYearID
    JOIN dbo.MasterHuntType mht ON htly.MasterHuntTypeID = mht.MasterHuntTypeID
    LEFT JOIN dbo.HuntApplicationLicense hal ON ha.HuntApplicationID = hal.HuntApplicationID
    LEFT JOIN dbo.DrawTicket dt ON ha.HuntApplicationID = dt.HuntApplicationID
    LEFT JOIN dbo.DrawTicketLicense won ON dt.DrawTicketID = won.DrawTicketID
    AND won.WasDrawn = 1
    LEFT JOIN dbo.DrawSelectionMethod dsm ON dt.DrawSelectionMethodID = dsm.DrawSelectionMethodID
    LEFT JOIN dbo.StatusCode lStatus ON dt.StatusCodeID = lStatus.StatusCodeID
    JOIN dbo.DrawTicketHuntChoice dthc ON dt.DrawTicketID = dthc.DrawTicketID
    CROSS APPLY dbo.tvf_GetHuntApplicationPartyCount(ha.HuntApplicationID) hapc
    CROSS APPLY dbo.tvf_GetAvgPreferencePoints(dt.DrawTicketID) app
    WHERE 1 = 1
    AND htly.MasterHuntTypeID = @iMasterHuntTypeID
    AND htly.LicenseYear = @iLicenseYear
    AND dt.StatusCodeID = @iDrawTicketStatusCodeID
    AND dthc.WasDrawn = @iHuntChoiceWasDrawn
    GROUP BY ha.HuntApplicationID,
    ha.PartyNumber,
    mht.[Name],
    htly.LicenseYear,
    lStatus.[Status],
    --isnull(dbo.udf_GetHuntApplicationPartyCount(ha.HuntApplicationID), 0),
    isnull(hapc.MemberCount, 0),
    won.DrawTicketID,
    dt.PreDrawNonResidentMemberCount,
    --dbo.udf_GetAvgPreferencePoints(dt.DrawTicketID),
    app.PreferencePointAverage,
    CASE
    WHEN ha.Quantity > 1 THEN NULL
    ELSE dt.PreDrawRandomNumber
    END,
    dsm.[Name],
    dt.DrawnSequence,
    dt.PreferencePointRank,
    dt.DrawID,
    dt.RandomRank
    ORDER BY htly.LicenseYear DESC,
    mht.Name,
    lStatus.[Status],
    dt.DrawID,
    PreferencePointAverage DESC,
    PreDrawRandomNumber,
    ha.PartyNumber

    对应的表值函数:

    ​CREATE FUNCTION [dbo].[tvf_GetAvgPreferencePoints]
    (@DrawTicketID INT)
    RETURNS TABLE WITH SCHEMABINDING
    AS
    RETURN
    (
    SELECT TOP 1
    CONVERT(DECIMAL, dt.PreDrawPreferencePointTotal) / NULLIF(CONVERT(DECIMAL, dt.PreDrawMemberCount),0) as PreferencePointAverage
    FROM dbo.DrawTicket dt
    WHERE dt.DrawTicketID = @DrawTicketID
    )
    GO

    改写后执行时间从40s降低到16s,对于倾斜列的优化速度更为明显

  • 相关阅读:
    数据结构-树与二叉树-思维导图
    The last packet successfully received from the server was 2,272 milliseconds ago. The last packet sent successfully to the server was 2,258 milliseconds ago.
    idea连接mysql报错Server returns invalid timezone. Go to 'Advanced' tab and set 'serverTimezone' property
    redis学习笔记
    AJAX校验注册用户名是否存在
    AJAX学习笔记
    JSON学习笔记
    JQuery基础知识学习笔记
    Filter、Listener学习笔记
    三层架构学习笔记
  • 原文地址:https://www.cnblogs.com/database/p/11953143.html
Copyright © 2011-2022 走看看