标量函数在存储过程中使用时在 SQL Server 中发生请求超时问题
Posted
技术标签:
【中文标题】标量函数在存储过程中使用时在 SQL Server 中发生请求超时问题【英文标题】:Scalar function occurring request timeout issue in SQL Server while using in stored procedure 【发布时间】:2017-05-23 10:08:48 【问题描述】:这是 Salar 函数。我在带有多个参数的存储过程中使用它。对于小的结果,这很好,但对于大数据,它会超时并且执行时间也很长。请分享一些其他替代或一些增强功能
ALTER FUNCTION [dbo].[FNGETMULIPLEASSIGNESS_NEW2]
(
@TIMELINEID INT,
@MILSTONEID INT,
@TASKID INT
)
RETURNS varchar(max)
AS
BEGIN
DECLARE @Assignees varchar(max)='', @isExists bit=0
if(@TASKID=0)
BEGIN
Select @Assignees = @Assignees+ FIRSTNAME +' ' + LASTNAME+', '
FROM CASETIMELINEPEOPLE
INNER JOIN USERDETAIL ON
CASETIMELINEPEOPLE.PEOPLEUSERID=USERDETAIL.USERID
WHERE (CASETIMELINEID= @TIMELINEID) AND
(TEMPLATEMILESTONEID=@MILSTONEID) AND
(TEMPLATETASKID is null) and CASETIMELINEPEOPLE.isdeleted=0
END
else
BEGIN
Select @Assignees = @Assignees+ FIRSTNAME +' ' + LASTNAME+','
FROM CASETIMELINEPEOPLE
INNER JOIN USERDETAIL ON
CASETIMELINEPEOPLE.PEOPLEUSERID=USERDETAIL.USERID
WHERE (CASETIMELINEID= @TIMELINEID) AND
(TEMPLATEMILESTONEID=@MILSTONEID) AND
(TEMPLATETASKID=@TASKID) and CASETIMELINEPEOPLE.isdeleted=0
END
SELECT @Assignees=SUBSTRING(@Assignees, 0,LEN(@Assignees))
RETURN @Assignees
END
【问题讨论】:
我没有看到太多改进 SELECT 的替代方案。也许通过引用字段向表中添加一些索引可能会有所帮助。 您可以通过WHERE COALESCE(TEMPLATETASKID, 0) = @TASKID
避免 if/else(或者只是条件中的普通 OR)
感谢酒精饮料。那里缺少索引
【参考方案1】:
使用内联表值函数将提高性能。
参考:
When is a SQL function not a function? "If it’s not inline, it’s rubbish." - Rob Farley Inline Scalar Functions - Itzik Ben-Gan Scalar functions, inlining, and performance: An entertaining title for a boring post - Adam Machanic TSQL User-Defined Functions: Ten Questions You Were Too Shy To Ask - Robert Sheldon这是使用
stuff()
with select ... for xml path ('')
method of string concatenation 的标量函数的内联表值函数版本:
create function dbo.fn_get_multiple_assigness_itvf (
@timelineid int
, @milstoneid int
, @taskid int
) returns table as return (
select Assignees = stuff((
select ',' + firstname + ' ' + lastname
from casetimelinepeople ctp
inner join userdetail ud
on ctp.peopleuserid=ud.userid
where casetimelineid = @timelineid
and templatemilestoneid = @milstoneid
and (templatetaskid = @taskid
or (@taskid = 0 and templatetaskid is null)
)
and ctp.isdeleted=0
for xml path (''), type).value('.','nvarchar(max)')
,1,1,'')
)
go
rextester 演示:http://rextester.com/UZTJS46485
测试设置:
create table casetimelinepeople (
casetimelineid int
, peopleuserid int
, templatemilestoneid int
, templatetaskid int
, isdeleted bit not null default 0
);
insert into casetimelinepeople values
(1,1,1,null,0)
,(1,2,1,null,0)
,(1,3,1,null,0)
,(1,2,1,1,0)
,(1,3,1,1,0)
create table userdetail (
userid int not null
, firstname varchar(32) not null
, lastname varchar(32) not null);
insert into userdetail values
(1, 'Some', 'One')
,(2, 'Avinash', 'Raikwar')
,(3, 'Sql','Zim');
go
并像这样查询内联表值函数:
select *
from dbo.fn_get_multiple_assigness_itvf(1,1,0)
返回
+----------------------------------+
| Assignees |
+----------------------------------+
| Some One,Avinash Raikwar,Sql Zim |
+----------------------------------+
select *
from dbo.fn_get_multiple_assigness_itvf(1,1,1)
返回:
+-------------------------+
| Assignees |
+-------------------------+
| Avinash Raikwar,Sql Zim |
+-------------------------+
使用cross apply()
为查询中的每一行调用函数:
select *
from casetimelinepeople ctp
cross apply dbo.fn_get_multiple_assigness_itvf(
ctp.casetimelineid
, ctp.templatemilestoneid
, ctp.templatetaskid
) x
返回:
+----------------+--------------+---------------------+----------------+-----------+----------------------------------+
| casetimelineid | peopleuserid | templatemilestoneid | templatetaskid | isdeleted | Assignees |
+----------------+--------------+---------------------+----------------+-----------+----------------------------------+
| 1 | 1 | 1 | NULL | False | Some One,Avinash Raikwar,Sql Zim |
| 1 | 2 | 1 | NULL | False | Some One,Avinash Raikwar,Sql Zim |
| 1 | 3 | 1 | NULL | False | Some One,Avinash Raikwar,Sql Zim |
| 1 | 2 | 1 | 1 | False | Avinash Raikwar,Sql Zim |
| 1 | 3 | 1 | 1 | False | Avinash Raikwar,Sql Zim |
+----------------+--------------+---------------------+----------------+-----------+----------------------------------+
【讨论】:
Rob Farley 的那篇文章非常棒。感谢您发布它。 @AlanBurstein 很高兴你喜欢它!以上是关于标量函数在存储过程中使用时在 SQL Server 中发生请求超时问题的主要内容,如果未能解决你的问题,请参考以下文章