`

SQL Server 性能优化之——T-SQL TVF和标量函数

阅读更多
原帖地址:http://www.cnblogs.com/BoyceYang/p/3143518.html

阅读导航


1. TVF(-值行数Table-Valued Functions)


        a. 创建TVF


        b. 使用TVF的低性能T-SQL


        c. 使用临时表代替TVF


2. 标量函数


3. 替代标量函数


    1). 临时表


    2). 持久化确定的计算列


    3). 使用计划更新工作


        a. 创建标量函数


        b. 使用临时表替换标量函数


        c. 使用持久化确定的计算列


        d. 使用计划工作代替标量函数


 


上一篇介绍了关于“临时表、表变量和Union优化”这次转向关注定义函数——也就是表-值函数、标量函数。


UDF(用户定义函数,User defined Function)对于集中精力处理业务逻辑很方便,因为可以在UDF中指定一组业务逻辑,其中可以设计多个存储过程和一些特定的查询语句。但是,由于UDF对CPU的大量请求可能导致性能下降


 


1. TVF(-值行数Table-Valued Functions)


一般情况,当使用TVF与一个对象内联接,如果该对象没有索引将会导致TVF像索引扫描或表扫描一样做扫描操作。


作为一个选择,可以创建临时表,临时表上创建适当的聚集索引或非聚集索引。


详情如下:



  • 创建适当的临时表。

  • 根据T-SQL创建适当的聚集索引和非聚集索引。

  • 将TVF的数据插入到临时表中。

  • 用临时表和相关的列替换每一个TVF。

  • 在查询语句执行结束后,删除临时表。


                注意,临时表的性能提升是超过表参数,在上一篇博客中提到的,表参数不支持索引。


例子:


a. 创建TVF:




   1: use [MyDemo]

<!--CRLF-->
   2: go

<!--CRLF-->
   3: alter FUNCTION Dep_Salaries1

<!--CRLF-->
   4: (

<!--CRLF-->
   5: @empid int

<!--CRLF-->
   6: )

<!--CRLF-->
   7: RETURNS @table table

<!--CRLF-->
   8: (

<!--CRLF-->
   9: Department int,

<!--CRLF-->
  10: Salary_Max int,

<!--CRLF-->
  11: Salary_Min int

<!--CRLF-->
  12: )

<!--CRLF-->
  13: AS

<!--CRLF-->
  14: BEGIN

<!--CRLF-->
  15: declare @Department int = (select S.deptid from Employees s where s.empid=@empid)

<!--CRLF-->
  16: insert into @table

<!--CRLF-->
  17: SELECT S.deptid , max (Salary) , MIN(Salary) FROM Employees s inner join Departments T ON S.deptid =T.deptid group by S.deptid having S.deptid =@Department

<!--CRLF-->
  18: RETURN

<!--CRLF-->
  19: END

<!--CRLF-->
  20: GO

<!--CRLF-->



b. 使用TVF的低性能T-SQL:




   1: alter procedure Unperformant_SP1

<!--CRLF-->
   2: @empid int

<!--CRLF-->
   3: as

<!--CRLF-->
   4: begin

<!--CRLF-->
   5: select T.deptid as department_name , s.* from Dep_Salaries1 (@empid )S inner join Departments T ON S.Department =T.deptid

<!--CRLF-->
   6: end

<!--CRLF-->


 


c. 使用临时表代替TVF:




   1: go

<!--CRLF-->
   2: alter procedure Performant_SP1

<!--CRLF-->
   3: @empid int

<!--CRLF-->
   4: as

<!--CRLF-->
   5: begin

<!--CRLF-->
   6: create table #table

<!--CRLF-->
   7: (

<!--CRLF-->
   8: Department int,

<!--CRLF-->
   9: Salary_Max int,

<!--CRLF-->
  10: Salary_Min int

<!--CRLF-->
  11: )

<!--CRLF-->
  12: create clustered index #table_index1 on #table (Department)

<!--CRLF-->
  13: insert into #table select * from Dep_Salaries1 (@empid )

<!--CRLF-->
  14: select T.deptid as department_name , s.* from #table S inner join Departments T ON S.Department =T.deptid

<!--CRLF-->
  15: end

<!--CRLF-->


在使用具体的查询和数据时,还是应该进行必要的性能测试,发现最适合自己情况的解决方案。



2. 标量函数


标量函数,对于确定存储过程或特定查询语句的聚合值、累计值、差分值非常方便的,但是对性能是有损失的,尤其使用大数据,标量函数将执行每一个记录。


 


3. 替代标量函数



1). 临时表


使用临时表,但是这个解决方案有一点不同于TVF的情况,这里希望完全放弃标量函数并且也不去直接使用内部T-SQL代码。



2). 持久化确定的计算列


持久化确定的计算列值不是每次选择都重新计算该列,而只是在创建时计算一次。因此,这时可以添加不同的T-SQL语句提高性能,因为这样可以减少进程的开销。


这个功能可以通过下面步骤添加:



  • 增加一个新的计算列存储标量函数的结果。

  • 启用这个计算列的持久化功能。

  • 在列(不管是主键列还是包含列)上设置适当的索引。


             但是要注意持久化功能还是有一些限制,如:


                   i. 计算列不应该使用任何其他记录的聚合功能。


                   ii. 计算列不应该使用调用外部系统过程的功能。


                   iii. 计算列不应该使用任何其他表的其他字段的功能。


                   iv. 计算列生成最好是使用系统提供的功能,例如:Convert、Cast、Replace等等,并且开发者不能创建UDF,因为UDF通常和该功能相矛盾。


这仅仅是适用于持久化的功能,但是可以添加计算列索引,应该通过确定计算数据的精确类型(如,INT、 Bigint、 DateTime和decimal)精确列的类型。如果数据类型不精确,可以添加这些列为索引的包含列的一部分,但不是主键列的一部分。



3). 使用计划更新工作


如果不可能使用持久化确定的计算列,可以创建普通列并同时创建计划更新工作,更新这些列的标量函数输出,然后用T-SQL代替标量函数并且在T-SQL中使用这些列。具体如下:



a. 创建标量函数:




   1: use [Workshops]

<!--CRLF-->
   2: go

<!--CRLF-->
   3: create FUNCTION Salary_Tax

<!--CRLF-->
   4: (

<!--CRLF-->
   5: @empid int

<!--CRLF-->
   6: )

<!--CRLF-->
   7: RETURNS float

<!--CRLF-->
   8: AS

<!--CRLF-->
   9: BEGIN

<!--CRLF-->
  10: declare @salary int = (select (S.salary-100) from Employees s where s.empid=@empid)

<!--CRLF-->
  11: RETURN @salary

<!--CRLF-->
  12: END

<!--CRLF-->
  13: GO

<!--CRLF-->
  14: --性能低些的标量函数

<!--CRLF-->
  15: Select empid ,dbo.Salary_Tax (empid) as 'SalaryWithTax' from Employees

<!--CRLF-->


 


b. 使用临时表替换标量函数:




   1: Create Table #temp (Empid int primary key clustered , Salary_Tax float)

<!--CRLF-->
   2: Create nonclustered index #temp_Index1 on #temp (Empid ) include (Salary_Tax )

<!--CRLF-->
   3: insert into #temp select Empid ,(Salary-100) as salary_Tax from Employees

<!--CRLF-->
   4: select * from #temp

<!--CRLF-->


 


c. 使用持久化确定的计算列:




   1: ALTER TABLE dbo.Employees ADD Salary_Tax AS Salary-100 PERSISTED

<!--CRLF-->
   2: Create nonclustered index Employees_Index1 on Employees (Empid, Salary_Tax )

<!--CRLF-->
   3: select empid ,Salary_Tax from Employees

<!--CRLF-->


 


d. 使用计划工作代替标量函数:




   1: ALTER TABLE dbo.Employees ADD Salary_Tax1 float, update_flag bit

<!--CRLF-->
   2: ALTER TABLE dbo.Employees ADD CONSTRAINT DF_Employees_update_flag DEFAULT 0 FOR update_flag

<!--CRLF-->
   3: Schedule the below DML update by an appropriate frequency according to your workload

<!--CRLF-->
   4: Update Employees set Salary_Tax1=Salary-100 WHERE UPDATE_Flag=0

<!--CRLF-->
   5: Then you can include the below select query within your stored procedure.

<!--CRLF-->
   6: select empid , Salary_Tax1 from Employees

<!--CRLF-->


 


上班时间到了!


期待下一篇吧!


任何的优化的不是绝对的,只有适应自己环境才是最好的,性能测试是必要。


在此谢谢读完这篇博客,有什么写的不对的地方请指正


有帮助就推荐下,有感想就写下留言,不满意也写下留言,有问题就更正。

本文链接

分享到:
评论

相关推荐

    sql server 自定义函数

    在SQL Server中,自定义函数(User-Defined Functions, UDFs)是数据库开发者和管理员扩展数据库功能的重要工具。它们允许我们创建自己的函数,以处理特定的数据操作或业务逻辑,这些函数可以像内置函数一样在SQL...

    Python实现TVF-EMD-LSTM时间序列预测(完整源码和数据)

    1.Python实现TVF-EMD-LSTM时间序列预测(完整源码和数据) anaconda + pycharm + python +Tensorflow 注意事项:保姆级注释,几乎一行一注释,方便小白入门学习! 2.代码特点:参数化编程、参数可方便更改、代码编程...

    第19章 使用CLR访问SQL Server 2008.zip

    在SQL Server 2008中,使用CLR...总之,使用CLR访问SQL Server 2008是提升数据库功能和效率的有效途径,但需要谨慎评估安全性和性能影响。开发者应当熟悉.NET编程和SQL Server的管理,以充分利用这一强大的技术。

    SQLServer中如何将一个字段的多个记录值合在一行显示

    SQL Server 是一种关系型数据库管理系统,具有强大的数据处理能力和存储能力。在实际应用中,我们经常需要将一个字段的多个记录值合并到一行显示,以便于数据分析和展示。在本文中,我们将介绍如何在 SQL Server ...

    TVF-EMD(时变滤波器的经验模态分解)可直接替换

    通过以上内容的介绍,我们可以看出TVF-EMD不仅在理论上有其独特之处,而且在实际应用中也展现出了极高的价值。无论是对于科研工作者还是工业界的专业人士来说,掌握这项技术都将大有益处。希望本文能够帮助读者更好...

    FLINK SQL 在快手的扩展和实践-Flink Forward Asia 2021.pdf

    快手通过对Flink SQL的扩展和优化,不仅提升了性能和稳定性,而且通过高阶窗口函数增加了分析的维度和深度。快手的经验对其他大数据公司也具有借鉴意义,尤其是在数据流处理、实时分析和批处理集成方面。 未来展望...

    Eval-SQL.NET:SQL Eval函数使用C#语法在SQL Server中动态评估表达式

    不要错过通过用户定义函数(UDF)和表值函数(TVF)将简单表达式的查询性能显着提高300% ,将复杂代码的查询性能显着提高2000%以上的机会。 在SQL中使用分隔符分割字符串的基准 方法 1,000行 10,000行 100,000行...

    在SQL Server中将表值函数用作数组

    T-SQL表值函数分为内联表值函数和多语句表值函数。内联TVF的性能通常更好,因为它们可以被优化器更有效地处理,而多语句TVF则提供了更大的灵活性,可以包含复杂的逻辑。 创建T-SQL内联表值函数的基本语法如下: ```...

    在SQL Server中使用表值函数

    您可以通过提供的链接下载"Using-Table-Valued-Functions-in-SQL-Server.pdf"文档,了解更多关于在实际项目中使用表值函数的详细示例和最佳实践。此外,"Script.zip"可能包含示例脚本,供您动手实践和学习。 总之...

    DB2命令总汇 txt格式

    执行SQL脚本文件`my.sql`,`-t`表示跟踪模式,用于检查SQL语法错误;`-v`选项使输出更加详细;`-f`选项用于指定SQL脚本文件。 - **db2level** 该命令用来显示当前安装的DB2版本信息。 - **db2 "?" sql6031** ...

    变频器说明书大全系列-TVF7000.rar

    变频器说明书大全系列-TVF7000.rar是一个压缩包文件,包含了关于TVF7000系列变频器的详细技术资料,主要目的是帮助用户理解和操作这种高性能的变频器。TVF7000系列变频器是工业自动化领域广泛应用的一种设备,它主要...

    如何拆分Microsoft SQL Server表行数据

    但在这个案例中,由于我们可能需要兼容SQL Server 2005及更低版本,我们可以使用其他函数,如`CHARINDEX()`和`SUBSTRING()`。以下是一个示例: ```sql DECLARE @Skills NVARCHAR(MAX) = '编程,数据库设计,项目...

    变频器说明书大全系列-TVF7100.rar

    《变频器说明书大全系列——TVF7100》 在现代工业自动化领域,变频器扮演着至关重要的角色,它能通过调整电机的供电频率来改变电机的转速,实现对机械设备的精确控制。TVF7100系列变频器是其中一款广泛应用的产品,...

    变频器说明书大全系列-TVF1000.rar

    《变频器说明书大全系列——TVF1000》 在现代工业自动化领域,变频器扮演着至关重要的角色。变频器是一种能够改变电机输入电源频率的电力控制设备,通过调整频率来控制电动机的转速和扭矩,从而实现对机械设备的...

    变频器说明书大全系列-TVF5000.rar

    这个系列的变频器是工业自动化领域常见的一种设备,用于控制电动机的速度和转矩,以适应不同生产需求或优化能源效率。下面将对TVF5000系列变频器及其使用手册中的关键知识点进行详细介绍。 1. 变频器的基本原理:...

    变频器说明书大全系列-TVF8000.rar

    3. **参数设置**:TVF8000变频器有许多可调参数,用于优化其性能以适应不同应用。说明书将列出所有可用参数及其作用,指导用户进行正确的设定。 4. **操作与控制**:文档会解释如何使用面板控制、外部信号控制、...

    变频器说明书大全系列-tvf3000.rar

    变频器,作为一种电力控制设备,广泛应用于工业自动化领域,...全面理解并熟练运用TVF3000变频器的说明书,对于操作者来说至关重要,它不仅可以确保设备正常运行,还能帮助优化系统性能,减少故障发生,提升生产效率。

    变频器说明书大全系列-TVF2000.rar

    TVF2000变频器采用了现代微处理器技术,具有高效率、低噪音和出色的动态性能。 二、TVF2000变频器特性 1. 控制方式:TVF2000支持多种控制方式,包括V/F控制(电压/频率比控制)、无速度传感器矢量控制、有速度...

    TVF Caculate

    在这个2D版本的TVF框架中,可能包含了一系列的算法和函数,用于读取边缘数据、构建张量场、执行投票过程、并最终输出处理后的结果。通过研究`create_stick_tensorfield.m`脚本以及可能的其他相关代码,我们可以深入...

Global site tag (gtag.js) - Google Analytics