程序高 CPU 使用率
Procedure high CPU usage
我们有一个应用程序 运行 特定 SP 的请求率很高。在 SQLServer Profiler 中,我看到这个 SP 的使用率很高 CPU,但是当我 运行 改变 SP 时(改变不改变 SP 逻辑,它只是改变现有的 SP!)cpu 使用去下降,几个小时后再次上升。
我真的很困惑为什么这个动作可以降低 CPU 的使用率,我该如何解决?
SP的定义如下:
ALTER PROCEDURE [dbo].[MySP]
@UId BigInt ,
@Ml int,
@MXL int,
@R1 int,
@R2 int,
@R3 int,
@R4 int ,
@debugmode bit
AS
If(@Ml < 1)
Set @Ml = 1
If (@MXL > 99 )
Set @MXL = 99
If (@Ml >= 42 OR @debugmode = 1)
Begin
with
tmp_one as
(
SELECT
R.Id as RID
FROM [U] as U
Inner Join
[R] as R
On R.UId = U.Id
WHERE ([R].[L] BETWEEN @Ml AND @MXL)
AND (R.UId <> @UId)
AND (0 = [U].[Status])
AND (1 = [U].[ActionStatus])
AND ((ABS((BINARY_CHECKSUM(NEWID(),R.Id)))% 10000)/100 ) BETWEEN @R1 AND (@R1 + 10)
)
Select top 10 RID
From tmp_one
Order By RID
End
Else
Begin
with
tmp_one as
(
SELECT
R.Id as RID
FROM [User] as U
Inner Join
[Rooster] as R
On R.UID = U.Id
WHERE ([R].[L] BETWEEN @Ml AND @MXL)
AND (0 = [U].[Status])
AND (1 = [U].[ActionStatus])
AND ((ABS((BINARY_CHECKSUM(R.Id,NEWID())))% 10000)/100 ) BETWEEN @R1 AND (@R1 + 10)
),
tmp_two as
(
Select tmp_one.RID as RID
From tmp_one
Where ((ABS((BINARY_CHECKSUM(RID,NEWID())))% 10000)/100 ) BETWEEN @R2 AND (@R2 + 10)
),
tmp_three as
(
Select RID as RID
From tmp_two
Where ((ABS((BINARY_CHECKSUM(NEWID())))% 10000)/100 ) BETWEEN @R3 AND (@R3 + 10)
),
tmp_four as
(
Select TOP 100 RID as RID
From tmp_three
Where ((ABS((BINARY_CHECKSUM(NEWID())))% 10000)/100 ) BETWEEN @R4 AND (@R4 + 10)
)
Select TOP(10)
RID
From tmp_four
Order By RID
End
我发现参数嗅探有问题!
我通过声明局部变量并将参数放在这些变量上来修复它。
一些关于 SQL 服务器参数嗅探的最佳文章:
http://blogs.msdn.com/b/turgays/archive/2013/09/10/parameter-sniffing-problem-and-workarounds.aspx
http://blogs.technet.com/b/mdegre/archive/2012/03/19/what-is-parameter-sniffing.aspx
我们有一个应用程序 运行 特定 SP 的请求率很高。在 SQLServer Profiler 中,我看到这个 SP 的使用率很高 CPU,但是当我 运行 改变 SP 时(改变不改变 SP 逻辑,它只是改变现有的 SP!)cpu 使用去下降,几个小时后再次上升。 我真的很困惑为什么这个动作可以降低 CPU 的使用率,我该如何解决?
SP的定义如下:
ALTER PROCEDURE [dbo].[MySP]
@UId BigInt ,
@Ml int,
@MXL int,
@R1 int,
@R2 int,
@R3 int,
@R4 int ,
@debugmode bit
AS
If(@Ml < 1)
Set @Ml = 1
If (@MXL > 99 )
Set @MXL = 99
If (@Ml >= 42 OR @debugmode = 1)
Begin
with
tmp_one as
(
SELECT
R.Id as RID
FROM [U] as U
Inner Join
[R] as R
On R.UId = U.Id
WHERE ([R].[L] BETWEEN @Ml AND @MXL)
AND (R.UId <> @UId)
AND (0 = [U].[Status])
AND (1 = [U].[ActionStatus])
AND ((ABS((BINARY_CHECKSUM(NEWID(),R.Id)))% 10000)/100 ) BETWEEN @R1 AND (@R1 + 10)
)
Select top 10 RID
From tmp_one
Order By RID
End
Else
Begin
with
tmp_one as
(
SELECT
R.Id as RID
FROM [User] as U
Inner Join
[Rooster] as R
On R.UID = U.Id
WHERE ([R].[L] BETWEEN @Ml AND @MXL)
AND (0 = [U].[Status])
AND (1 = [U].[ActionStatus])
AND ((ABS((BINARY_CHECKSUM(R.Id,NEWID())))% 10000)/100 ) BETWEEN @R1 AND (@R1 + 10)
),
tmp_two as
(
Select tmp_one.RID as RID
From tmp_one
Where ((ABS((BINARY_CHECKSUM(RID,NEWID())))% 10000)/100 ) BETWEEN @R2 AND (@R2 + 10)
),
tmp_three as
(
Select RID as RID
From tmp_two
Where ((ABS((BINARY_CHECKSUM(NEWID())))% 10000)/100 ) BETWEEN @R3 AND (@R3 + 10)
),
tmp_four as
(
Select TOP 100 RID as RID
From tmp_three
Where ((ABS((BINARY_CHECKSUM(NEWID())))% 10000)/100 ) BETWEEN @R4 AND (@R4 + 10)
)
Select TOP(10)
RID
From tmp_four
Order By RID
End
我发现参数嗅探有问题! 我通过声明局部变量并将参数放在这些变量上来修复它。
一些关于 SQL 服务器参数嗅探的最佳文章: http://blogs.msdn.com/b/turgays/archive/2013/09/10/parameter-sniffing-problem-and-workarounds.aspx
http://blogs.technet.com/b/mdegre/archive/2012/03/19/what-is-parameter-sniffing.aspx