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 当一个函数是内联和虚函数时,会发生代码替换或使用虚表调用吗? 为了弄清楚内联和虚函数,让我们将 ...
随机推荐
- linux:用户和组文件解释(/etc/passwd、/etc/shadow、/etc/group、/etc/gshadow)
一.用户文件:/etc/passwd [root@pinfun6 ~]# cat /etc/passwd root:x:0:0:root:/root:/bin/bash 1 2 3 4 5 6 7 | ...
- C++ 引用深入理解
1.引用作为变量的别名存在,因此可以在一些场合代替指针. 引用相当于指针来说具有更好的可读性和实用性. 例如: /* 编译环境 gcc version 7.4.0 (Ubuntu 7.4.0-1ubu ...
- 解决jenkins的Console Output中文乱码
1.本地机器设置环境变量(设置后需要注销计算机才能生效) key: JAVA_TOOL_OPTIONS value:-Dfile.encoding=UTF- 2. 通过Jenkins全局设置的方式 ...
- Smoke Testing
[Smoke Testing 释义] Smoke Testing 的概念最早源于制造业,用于测试管道.测试时,用鼓风机往管道里灌烟,看管壁外面是否有烟冒出来,以便检验管道是否有缝隙.这一测试显然比较初 ...
- java 可变长度参数列表
public class Main11 { public static void print(Integer... args){ if(args !=null) System.out.println( ...
- JavaScript中实现li向上轮播
在网上找了很久,没有找到合适的模板,其实我这个也是公司用的,希望以后也能复用,节省时间 function scrollAuto(scrollBox, list){//两个参数分别填列表的ul的clas ...
- Qt设置生成的exe文件图标
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/qq_37354286/article/d ...
- “12306”是如何支撑百万QPS的?
来源:掘金 作者:绘你一世倾城 链接:https://juejin.im/post/5d84e21f6fb9a06ac8248149 秒杀系统的艺术 12306抢票,极限并发带来的思考? 每到节假日期 ...
- puppet之模板和类
puppet之模板和类 不同节点布置资源 vim /etc/puppet/manifests/site.pp 1 import "nodes/*.pp" 建立节点文件 mkdir ...
- Linux下单机部署ELK日志收集、分析环境
一.ELK简介 ELK是elastic 公司旗下三款产品ElasticSearch .Logstash .Kibana的首字母组合,主要用于日志收集.分析与报表展示. ELK Stack包含:Elas ...