我需要为以下脚本大幅提高速度。我正在考虑删除表值函数并将所有内容放在存储过程中。但在我这样做之前,我想让专家们看看,并为我提供解决方案或一些指示。脚本具有分页功能,需要以某种方式保留在原位。
首先是商店程序:
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
ALTER PROC [sbuser].[sp_MemberSearch]
@UserName varchar(200) = null,
@MemberID bigint = null,
@PG int = 1,
@ROWCT numeric(18,2) = 1,
@COLCT numeric(18,2) = 1,
@MODE varchar(50)
AS
IF @MODE = 'MEMBERSEARCH'
BEGIN
SELECT
MemberID, -- 0
UserName, -- 1
LastLogin, -- 2
PrCity, -- 3
Abbr, -- 4
Country, -- 5
AvatarMed, -- 6
Gender, -- 7
HasImages, -- 8
HasVideo, -- 9
HasAudio, -- 10
Domain, -- 11
DisplayName, -- 12
CreateDate, -- 13
Claimed, -- 14
PG, -- 15
MAXPG, -- 16
TOTALRECS, -- 17
ProfileTypeID, -- 18
Zip, -- 19
PhoneNbr, -- 20
PrPhone -- 21
FROM sbuser.tf_FindMember(@UserName,@MemberID,@PG,@ROWCT,@COLCT)
END
这里是上面提到的表值函数:
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [sbuser].[tf_FindMember] (
@UserName varchar(200) = null,
@MemberID bigint = null,
@PG int = 1,
@ROWCT numeric(18,2) = 1,
@COLCT numeric(18,2) = 1 )
RETURNS @OUT TABLE (
MemberID bigint, -- 0
UserName varchar(200), -- 1
LastLogin datetime, -- 2
PrCity varchar(50), -- 3
Abbr varchar(5), -- 4
Country varchar(50), -- 5
AvatarMed varchar(50), -- 6
Gender varchar(50), -- 7
HasImages bit, -- 8
HasVideo bit, -- 9
HasAudio bit, -- 10
Domain varchar(100), -- 11
DisplayName varchar(255), -- 12
CreateDate datetime, -- 13
Claimed varchar(1), -- 14
PG int, -- 15
MAXPG int, -- 16
TOTALRECS int, -- 17
ProfileTypeID bigint, -- 18
Zip varchar(50), -- 19
PhoneNbr varchar(50), -- 20
PrPhone varchar(25)) -- 21
AS
BEGIN
DECLARE @START numeric(18,2)
DECLARE @END numeric(18,2)
DECLARE @SIZE numeric(18,2)
DECLARE @MAXPG numeric(18,2)
DECLARE @TOTALRECS numeric(18,2)
DECLARE @TOTALRECS_INT int
DECLARE @MAXPG_INT int
DECLARE @TOTALRECS_REMAINDER numeric(18,2)
SET @SIZE = @ROWCT * @COLCT
SET @Start = (((@PG - 1) * @Size) + 1)
SET @END = (@START + @SIZE - 1)
DECLARE @TMP1 TABLE (
TMPID bigint primary key identity(1,1),
MemberID bigint,
UserName varchar(200),
LastLogin datetime,
PrCity varchar(50),
Abbr varchar(5),
Country varchar(50),
AvatarMed varchar(50),
Gender varchar(50),
HasImages bit,
HasVideo bit,
HasAudio bit,
Domain varchar(100),
DisplayName varchar(255),
CreateDate datetime,
Claimed varchar(1),
ProfileTypeID bigint,
Zip varchar(50),
PhoneNbr varchar(50),
PrPhone varchar(25))
BEGIN
INSERT INTO @TMP1
SELECT
a.MemberID,
a.UserName,
a.LastLogin,
a.PrCity,
b.Abbr,
c.Country,
a.AvatarMed,
a.Gender,
sbuser.sf_MemberHasImages(a.MemberID),
sbuser.sf_MemberHasVideo(a.MemberID),
sbuser.sf_MemberHasAudio(a.MemberID),
d.Domain,
sbuser.sf_DisplayName(a.MemberID),
a.CreateDate,
a.Claimed,
a.ProfileTypeID,
a.Zip,
a.PhoneNbr,
a.PrPhone
FROM Member a
LEFT JOIN State b ON b.StateID = a.StateID
INNER JOIN Country c ON c.countryID = a.CountryID
INNER JOIN Region d ON d.RegionID = a.MemberRegionID
WHERE (sbuser.sf_DisplayName(a.MemberID) LIKE @UserName + '%')
AND a.MemberID <> @MemberID
ORDER BY a.Claimed DESC, sbuser.sf_MemberHasAvatar(a.MemberID) DESC, sbuser.sf_MemberHasMedia(a.MemberID) DESC
END
SELECT @TOTALRECS = MAX(TMPID) FROM @TMP1
SELECT @MAXPG = @TOTALRECS / @SIZE
SET @TOTALRECS_REMAINDER = @TOTALRECS % @SIZE
SET @MAXPG_INT = CAST(@MAXPG AS INT)
SET @TOTALRECS_INT = CAST(@TOTALRECS AS INT)
IF @TOTALRECS_REMAINDER > 0
BEGIN
SET @MAXPG_INT = @MAXPG_INT + 1
END
INSERT INTO @OUT
SELECT
MemberID,
UserName,
LastLogin,
PrCity,
Abbr,
Country,
AvatarMed,
Gender,
HasImages,
HasVideo,
HasAudio,
Domain,
DisplayName,
CreateDate,
Claimed,
@PG,
@MAXPG_INT,
@TOTALRECS_INT,
ProfileTypeID,
Zip,
PhoneNbr,
PrPhone
FROM @TMP1
WHERE (TmpID >= @Start) AND (TmpID <= @END)
RETURN
END
我相信这个脚本是由我的前任用软件编写的。我对T-SQL没有多少经验。我真的很感激你能提供的任何帮助来提高执行速度,因为现在我们的系统有超过40,000名成员,它已经变得非常慢。
非常感谢您一起来看看。我真的很感激!
最诚挚的问候,
保罗雅各布斯为了进一步提供帮助,缺少sf脚本:
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [sbuser].[sf_MemberHasImages](@MemberID bigint)
RETURNS BIT
AS
BEGIN
DECLARE @OUT BIT
SET @OUT = (SELECT CAST(COUNT(a.MemberImgID) AS BIT) From MemberImg a INNER JOIN MemberImgGallery b ON b.MemberImgGalleryID=a.MemberImgGalleryID
WHERE b.MemberID = @MemberID)
RETURN @out
END
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [sbuser].[sf_MemberHasAudio](@MemberID bigint)
RETURNS BIT
AS
BEGIN
DECLARE @OUT BIT
SET @OUT = (SELECT CAST(COUNT(MemberAudioID) AS BIT) FROM MemberAudio WHERE MemberID = @MemberID)
RETURN @OUT
END
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [sbuser].[sf_MemberHasVideo](@MemberID bigint)
RETURNS BIT
AS
BEGIN
DECLARE @OUT BIT
SET @OUT = (SELECT CAST(COUNT(MemberVideoID) AS BIT) FROM MemberVideo WHERE MemberID = @MemberID)
RETURN @OUT
END
答案 0 :(得分:0)
查看您发布的代码,流基本上是这样的:
IF @MODE = 'MEMBERSEARCH'
在名为[sp_MemberSearch]
的过程中(sbuser.sf_DisplayName(a.MemberID) LIKE @UserName + '%')
。这个曾经对代码的审查似乎是多余的。 这不应该调用UDF。建议重构代码以在存储过程中进行所有搜索。今天很可能它被用于许多存储过程,所以它很容易在当前设置中重复使用。并不可怕,但你可以采取另一种方式,特别是如果你使用的是SQL Server 2008.尝试将其重新设计为自己的存储过程。
UDF基本上执行一个包含3个重要部分/注意事项的选择:
LIKE
。对我来说,这意味着将EACH成员ID传递给函数,并根据ORDER BY
条件进行评估。
MemberHasAvatar
两种不同的UDF结果 - MemberHasMedia
和Member
- 显然希望这些结果在顶部排序。
4个表:State
,Country
,Region
,JOIN
- 是否在SELECT
ed列上正确编入索引?如果在没有WHERE
子句和ORDER BY
子句的任何/部分/全部的情况下运行此语句,这个WHERE (sbuser.sf_DisplayName(a.MemberID) LIKE @UserName + '%')
AND a.MemberID <> @MemberID
的执行情况如何?
可以改进分页方面以使用更新的TSQL语言功能,但它可能比您想要的更多。 ROW_NUMBER()
是改善的一部分。
目前尚不清楚该条款的真实含义是什么:@MemberID
这是否意味着我们不希望在搜索结果中包含@SearchPerformedByMemberID
,因为他们是执行搜索的成员?可能更好的变量名称适合DisplayName
?
您可能已经知道,数学部分对此函数/ proc不会产生任何可衡量的性能影响。
一些改进建议,YMMV!
Member
表格中存储sbuser.sf_DisplayName
,以避免拨打{{1}}。