• 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,对于倾斜列的优化速度更为明显

  • 相关阅读:
    Dictionary集合 字典
    装箱和拆箱
    List< >泛型集合
    Hashtable 键值对集合
    File 类 的基本操作
    简体转换繁体
    ArrayList集合长度的问题
    ArrayList  集合
    里式转换
    字符串中常用的方法
  • 原文地址:https://www.cnblogs.com/database/p/11953143.html
Copyright © 2020-2023  润新知