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

  • 相关阅读:
    当一组单选按钮中的一个选中,后文本框为只读属性
    在.net 环境下,进行了伪静态页面处理后,后台的Fckeditor就不能正常显示了
    PL/SQL Developer 8注册码
    选中checkbox后才能填写输入框
    net 试图加载格式不正确的程序。(Exception from HRESULT: 0x8007000B)
    在sql中将varchar型转换成int型再进行排序
    ASP.NET中显示农历时间
    改变自己,拥抱生活
    人生最不值得你去做的事情
    Oracle 中的周、月、日历的查询实现
  • 原文地址:https://www.cnblogs.com/database/p/11953143.html
Copyright © 2011-2022 走看看