博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
优化案例--多语句表值函数的影响
阅读量:6469 次
发布时间:2019-06-23

本文共 3451 字,大约阅读时间需要 11 分钟。

在SQL SERVER中,自定义函数可以划分成:

1.内联表值函数

2.多语句表值函数

3.标量值函数

上述三类自定义函数如果使用不当,就会造成性能问题,本片重点关注“多语句表值函数”。

 

在多语句表值函数在每次调用时都需要使用到一个临时表来存放返回值,因此如果频繁调用该函数,会影响tempdb的性能。

测试代码:

--=========================================================================--创建测试表GOSELECT * INTO TB001 FROM sys.all_objectsGOSELECT * INTO TB002 FROM sys.all_columnsGO--=========================================================================--创建内联表值函数CREATE FUNCTION [dbo].[ufn_GetTop2Columns2](        @object_ID BIGINT)RETURNS TABLE ASRETURN (    SELECT TOP(2) name AS ColumnName     FROM TB002    WHERE OBJECT_ID=@object_ID)GO--=========================================================================--多语句表值函数CREATE FUNCTION [dbo].[ufn_GetTop2Columns](    @object_ID BIGINT)RETURNS @result TABLE (    ColumnName NVARCHAR(200))ASBEGIN    INSERT INTO @result    SELECT TOP(2) name AS ColumnName     FROM TB002    WHERE OBJECT_ID=@object_ID    RETURN ENDGOSET STATISTICS IO ONSET STATISTICS TIME ONGO--=========================================================================--不使用表值函数SELECT *FROM TB001 AS T1CROSS APPLY (SELECT TOP(2) * FROM TB002 AS T2 WHERE T1.Object_id=T2.Object_id ) AS T3--运行结果--表 'Worktable'。扫描计数 1989,逻辑读取 15095 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。--表 'TB002'。扫描计数 1,逻辑读取 54 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。--表 'TB001'。扫描计数 1,逻辑读取 34 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。--SQL Server 执行时间:--CPU 时间 = 94 毫秒,占用时间 = 543 毫秒。--=========================================================================--使用多语句表值函数SELECT *FROM TB001 AS T1CROSS APPLY dbo.ufn_GetTop2Columns(T1.Object_id) AS T3--运行结果--表 '#756D6ECB'。扫描计数 1989,逻辑读取 1989 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。--表 'TB001'。扫描计数 1,逻辑读取 34 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。--SQL Server 执行时间:--CPU 时间 = 7129 毫秒,占用时间 = 7262 毫秒。--=========================================================================--内联表值函数SELECT *FROM TB001 AS T1CROSS APPLY dbo.ufn_GetTop2Columns2(T1.Object_id) AS T3--运行结果--表 'Worktable'。扫描计数 1989,逻辑读取 14736 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。--表 'TB002'。扫描计数 1,逻辑读取 54 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。--表 'TB001'。扫描计数 1,逻辑读取 34 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。--SQL Server 执行时间:--CPU 时间 = 62 毫秒,占用时间 = 186 毫秒。

多次运行发现,使用内联表值函数执行速度(186ms)快于未使用自定义函数的语句(543ms),而多语句表值函数的执行速度最慢(7262ms).

 

优化建议:

1. 将多语句表值函数改写成内联表值函数或不使用自定义函数的语句。

2. 将CROSS APPLY改写成INNER JOIN ,以减少多语句表值函数的调用次数

如将上面的语句改成:

CREATE FUNCTION [dbo].[ufn_GetTop2Columns3]()RETURNS @result TABLE (    ColumnName NVARCHAR(200),    Object_id BIGINT)ASBEGIN    INSERT INTO @result(ColumnName,Object_id)    SELECT ColumnName,Object_id    FROM    (SELECT ROW_NUMBER()OVER(PARTITION BY T2.Object_id ORDER BY T2.Object_id) AS RID,    T2.name AS ColumnName,    T2.Object_id     FROM TB002 AS T2     ) AS T3    WHERE RID<3    RETURN ENDGO--===================================================================--将CROSS APPLY改写成INNER JOIN,SELECT *FROM TB001 AS T1INNER JOIN [dbo].[ufn_GetTop2Columns3]() AS T3ON T1.Object_id=T3.Object_id--表 'Worktable'。扫描计数 0,逻辑读取 0 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。--表 'TB001'。扫描计数 1,逻辑读取 34 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。--表 '#28ED12D1'。扫描计数 1,逻辑读取 5 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。--SQL Server 执行时间:--CPU 时间 = 47 毫秒,占用时间 = 383 毫秒。

 

当然,不是所有的多语句表值函数都可以被改写,在优化时测试各种优化方案,寻找到一种最适合业务场景的方法。

 

转载地址:http://hhdko.baihongyu.com/

你可能感兴趣的文章
这就是我的研究生生活
查看>>
Meteor 项目完整 Demo ,涉及到大部分知识。 一款 Meteor 的 入门 Web App ,GitHub 开源。...
查看>>
反爬虫系列-JS参数篇
查看>>
我的友情链接
查看>>
sed & awk
查看>>
数据库集群技术
查看>>
阿里云ECS 镜像ubuntu16.04配置apache+mysql+php
查看>>
mysql5.7 innodb数据库备份工具Xtrabackup的安装
查看>>
nginx证书的设置
查看>>
spreadjs~~一个Excel在线编辑的工具
查看>>
实战讲解.htaccess文件rewrite规则
查看>>
我的友情链接
查看>>
2003年4月全国计算机等级考试二级C语言笔试试题及答案
查看>>
python2 to python3
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
PostgreSQL: percentile_cont vs percentile_disc
查看>>
安装PHP5.6(X64)+Apache2.4(X64)时,PHP中缺少php5apache2_4
查看>>
我的友情链接
查看>>
XenServer常用命令
查看>>