阅读导航

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]

   2: go

   3: alter FUNCTION Dep_Salaries1

   4: (

   5: @empid int

   6: )

   7: RETURNS @table table

   8: (

   9: Department int,

  10: Salary_Max int,

  11: Salary_Min int

  12: )

  13: AS

  14: BEGIN

  15: declare @Department int = (select S.deptid from Employees s where s.empid=@empid)

  16: insert into @table

  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

  18: RETURN

  19: END

  20: GO

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

   1: alter procedure Unperformant_SP1

   2: @empid int

   3: as

   4: begin

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

   6: end

c. 使用临时表代替TVF:

   1: go

   2: alter procedure Performant_SP1

   3: @empid int

   4: as

   5: begin

   6: create table #table

   7: (

   8: Department int,

   9: Salary_Max int,

  10: Salary_Min int

  11: )

  12: create clustered index #table_index1 on #table (Department)

  13: insert into #table select * from Dep_Salaries1 (@empid )

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

  15: end

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

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]

   2: go

   3: create FUNCTION Salary_Tax

   4: (

   5: @empid int

   6: )

   7: RETURNS float

   8: AS

   9: BEGIN

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

  11: RETURN @salary

  12: END

  13: GO

  14: --性能低些的标量函数

  15: Select empid ,dbo.Salary_Tax (empid) as 'SalaryWithTax' from Employees

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

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

   2: Create nonclustered index #temp_Index1 on #temp (Empid ) include (Salary_Tax )

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

   4: select * from #temp

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

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

   2: Create nonclustered index Employees_Index1 on Employees (Empid, Salary_Tax )

   3: select empid ,Salary_Tax from Employees

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

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

   2: ALTER TABLE dbo.Employees ADD CONSTRAINT DF_Employees_update_flag DEFAULT 0 FOR update_flag

   3: Schedule the below DML update by an appropriate frequency according to your workload

   4: Update Employees set Salary_Tax1=Salary-100 WHERE UPDATE_Flag=0

   5: Then you can include the below select query within your stored procedure.

   6: select empid , Salary_Tax1 from Employees

上班时间到了!

期待下一篇吧!

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

SQL Server 性能优化之——T-SQL TVF和标量函数的更多相关文章

  1. 【SQL Server性能优化】运用SQL Server的全文检索来提高模糊匹配的效率

    原文:[SQL Server性能优化]运用SQL Server的全文检索来提高模糊匹配的效率 今天去面试,这个公司的业务需要模糊查询数据,之前他们通过mongodb来存储数据,但他们说会有丢数据的问题 ...

  2. SQL Server 性能优化(一)——简介

    原文:SQL Server 性能优化(一)--简介 一.性能优化的理由: 听起来有点多余,但是还是详细说一下: 1.节省成本:这里的成本不一定是钱,但是基本上可以变相认为是节省钱.性能上去了,本来要投 ...

  3. SQL Server 性能优化之——系统化方法提高性能

    SQL Server 性能优化之——系统化方法提高性能 阅读导航 1. 概述 2. 规范逻辑数据库设计 3. 使用高效索引设计 4. 使用高效的查询设计 5. 使用技术分析低性能 6. 总结 1. 概 ...

  4. SQL Server性能优化与管理的艺术 附件下载地址

    首先感谢读者们对鄙人的支持,购买了<SQL Server性能优化与管理的艺术>,由于之前出版社的一些疏忽,附件没有上传成功,再次本人深表歉意. 请需要下载附件的读者从下面链接下载,谢谢: ...

  5. SQL Server性能优化(6)查询语句建议

    1. 如果对数据不是工业级的访问(允许脏读),在select里添加 with(nolock) ID FROM Measure_heat WITH (nolock) 2. 限制结果集的数据量,如使用TO ...

  6. SQL SERVER性能优化综述

    SQL SERVER性能优化综述 一个系统的性能的提高,不单单是试运行或者维护阶段的性能调优的任务,也不单单是开发阶段的事情,而是在整个软件生命周期都需要注意,进行有效工作才能达到的.所以我希望按照软 ...

  7. SQL Server 性能优化之RML Utilities:快速入门(Quick Start)(1)

      SQL Server 性能优化之RML Utilities:快速入门(Quick Start)(1) 安装Quick Start工具 RML(Replay Markup Language)是MS ...

  8. 【SQL Server性能优化】删除大量数据的方法比较

    原文:[SQL Server性能优化]删除大量数据的方法比较 如果你要删除表中的大量数据,这个大量一般是指删除大于10%的记录,那么如何删除,效率才会比较高呢? 而如何删除才会对系统的影响相对较小呢? ...

  9. SQL Server 性能优化之——重复索引

    原文 http://www.cnblogs.com/BoyceYang/archive/2013/06/16/3139006.html 阅读导航 1. 概述 2. 什么是重复索引 3. 查找重复索引 ...

随机推荐

  1. 移动端HTML5<video>视频播放优化实践[转]

    http://blog.csdn.net/u010918416/article/details/52705732 http://www.xuanfengge.com/html5-video-play. ...

  2. myeclipse项目编码方式彻底设置

    我们团队6月10号开始做龙泉瓯江青瓷有限公司的ERP系统,采用java语言开发,在开发时我们采用的是java的流行框架struts2,前端脚本都用jquery框架,开发IDE用的是myeclipse, ...

  3. 【转载】Java中的回车换行符/n /r /t

    source:http://hane00.blog.163.com/blog/static/1600615220126204446809/ '\r'是回车,'\n'是换行,前者使光标到行首,后者使光标 ...

  4. 【Git】简单地使用github当做远程共享仓库

    简单地使用github当做远程共享仓库 1.进入各自的github,选取一个人的github作为总的远程共享仓库,其余成员每次修改完项目后pull request请求合并自己的修改内容. 2.其余开发 ...

  5. mysql text字段判断是否为空

    mysql text字段判断是否为空 mysql text字段为空select * from `tableName` where `textField` is null or `textField` ...

  6. hdu 1312(DFS)

    Red and Black Tme Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tota ...

  7. Java程序员从笨鸟到菜鸟之(一百零一)sql注入攻击详解(二)sql注入过程详解

    在上篇博客中我们分析了sql注入的原理,今天我们就来看一下sql注入的整体过程,也就是说如何进行sql注入,由于本人数据库和网络方面知识有限,此文章是对网上大量同类文章的分析与总结,其中有不少直接引用 ...

  8. Taylor定理证明

    下图,单独打开查看 当n->inf时如果 Rn(c)趋0, c属于(a,x), 那么在区间(a,x) 内函数在a点生成的taylor级数收敛到函数f.

  9. Spring学习笔记 6. 尚硅谷_佟刚_Spring_Bean 之间的关系

    1,继承关系 首先从简单的代码来看,有一个Address类,配置文件有两个bean (1)Address类 package com.zsq; public class Address { privat ...

  10. 经验总结之Android framework开发

    本人在某做手机ROM的厂商工作近两年,虽然工作年限不长,但是对此类“工种”已有比较初步的认识,写下来供大家参考借鉴. framework的工作相对于其他比较成熟的软件开发类似,分为维护和需求开发. 需 ...