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,对于倾斜列的优化速度更为明显
SQL Server标量函数改写内联表值函数优化案例的更多相关文章
- SQL Server进阶(六)表表达式--派生表、公用表表达式(CTE)、视图和内联表值函数
概述 表表达式是一种命名的查询表达式,代表一个有效地关系表.可以像其他表一样,在数据处理中使用表表达式. SQL Server支持四种类型的表表达式:派生表,公用表表达式,视图和内联表值函数. 为什么 ...
- SQL Server 表表达式--派生表、公用表表达式(CTE)、视图和内联表值函数
概述 表表达式是一种命名的查询表达式,代表一个有效地关系表.可以像其他表一样,在数据处理中使用表表达式. SQL Server支持四种类型的表表达式:派生表,公用表表达式,视图和内联表值函数. 为什么 ...
- sql server 创建内联表值函数
表值函数就是返回table 的函数使用它可以方便的进行查询的处理 创建的代码如下: create FUNCTION returunclassfirstlist( -- Add the paramet ...
- sql server的一个字符串分割的表值函数方法
ALTER function [dbo].[BOSplit](@SourceSql nvarchar(max), --要分割的字段@StrSeprate varchar(10) --分割符 ...
- SQL Server进阶(十二)常用函数
在SQL 2012基础教程中列出子句是按照以下顺序进行逻辑处理. FROM WHERE GROUP BY HAVING SELECT ORDER BY FROM TableName WHERE Use ...
- T-SQL编程 —— 用户自定义函数(内嵌表值函数)
内嵌表值函数 接上 <T-SQL编程 -- 用户自定义函数(标量函数)> http://www.cnblogs.com/viusuangio/p/6212072.html 内嵌表值函数可以 ...
- inline(内联)函数
1,为小操作定义一个函数的好处是: a.可读性会强很多. b.改变一个局部化的实现比更改一个应用中的300个出现要容易得多 c.函数可以被重用,不必为其他的应用重写代码 ...
- C++中的内联成员函数与非内联成员函数
在C++中内联成员函数与非内联成员函数的可以分为两种情况: 1.如果成员函数的声明和定义是在一起的,那么无论有没有写inline这个成员函数都是内联的,如下: using namespace std; ...
- C++如何处理内联虚函数
http://blog.csdn.net/hedylin/article/details/1775556 当一个函数是内联和虚函数时,会发生代码替换或使用虚表调用吗? 为了弄清楚内联和虚函数,让我们将 ...
随机推荐
- webelement类的方法
webelement类的方法,常用的汇总如下: clear()清空 例如登录时先清空输入框中的内容 driver.find_element_by_id('username').clear() clic ...
- vscode如何使用?常用插件有哪些?
vscode下载 官网下载:https://code.visualstudio.com/ 一.汉化中文(官方下载默认为英文,英文好的小伙伴可直接跳过这步) 点击插件按钮搜索 Chinese, 在弹出的 ...
- 需求文档(PRD文档)
https://blog.csdn.net/zhangbijun1230/article/details/79451874
- 解决引入 lombok 注解不生效,Eclipse与IDEA集成 lombok
Eclipse -javaagent:lombok.jar -vmargs -javaagent:lombok.jar IDEA 添加依赖 <!--lombok 实体类注解--> < ...
- 将shell脚本的执行过程和执行结果导入到log文件中
[root@localhost scripts]# vim ping.sh #!/bin/bash set -x ##分步执行 exec &> /tmp/log.txt ##脚本执行的过 ...
- xrdp远程
安装图形界面 yum groupinstall "GNOME Desktop" 安装epel源 yum install epel* 安装xrdp yum --enablerepo= ...
- Directed Roads CodeForces - 711D (基环外向树 )
ZS the Coder and Chris the Baboon has explored Udayland for quite some time. They realize that it co ...
- php晚了8小时 PHP5中的时间相差8小时的解决办法
php页面顶部加一句date_default_timezone_set("Asia/Shanghai");或者直接在php.ini设置date.timezone=Asia/Shan ...
- BZOJ - 1036 树的统计Count (LCT)
LCT试炼题(代码量居然完爆树剖?) #include<bits/stdc++.h> using namespace std; ,inf=0x3f3f3f3f; ],flp[N],n,m, ...
- MFC界面库BCGControlBar v30.1新功能详解:Dialogs和Forms
亲爱的BCGSoft用户,我们非常高兴地宣布BCGControlBar Professional for MFC和BCGSuite for MFC v30.1正式发布!此版本包含themed find ...