Sql server 优化TSQL存储过程
我正在尝试调整下面的存储过程,因为它在我们的网站上每分钟被调用30k次Sql server 优化TSQL存储过程,sql-server,tsql,stored-procedures,query-optimization,Sql Server,Tsql,Stored Procedures,Query Optimization,我正在尝试调整下面的存储过程,因为它在我们的网站上每分钟被调用30k次 CREATE PROCEDURE [dbo].[mltHttpCallStatus] @SupplierId AS INTEGER, @CallIsGood AS BIT, @MaxWorkerThreads AS INT, @MaxIOThreads AS INT, @AvailWorkerThreads AS INT, @AvailIOT
CREATE PROCEDURE [dbo].[mltHttpCallStatus]
@SupplierId AS INTEGER,
@CallIsGood AS BIT,
@MaxWorkerThreads AS INT,
@MaxIOThreads AS INT,
@AvailWorkerThreads AS INT,
@AvailIOThreads AS INT,
@ScriptTypeId AS INT,
@SiteTypeId AS VARCHAR(50),
@ConnectionTime AS INT,
@SiteName AS VARCHAR(50),
@HostName AS VARCHAR(50)
AS
--DEBUG BEN (Flight details keep failing) 07012008 19:30
--Return
SET NOCOUNT ON
DECLARE @GoodCalls AS INT,
@BadCalls AS INT
SET @BadCalls = 0
SET @GoodCalls = 0
IF @CallIsGood = 1
SET @GoodCalls = 1
ELSE
SET @BadCalls = 1
UPDATE HttpCallStatus_tbl SET
GoodCalls = GoodCalls + @GoodCalls,
BadCalls = BadCalls + @BadCalls,
TotalConnectionTime = TotalConnectionTime + @ConnectionTime
--WHERE dbo.datepart_fn(DayDate) = dbo.datepart_fn(getDate())
WHERE DATEADD(dd, 0, DATEDIFF(dd, 0, DayDate)) = DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
AND DATEPART(HOUR, DayDate) = DATEPART(HOUR, getDate())
AND SupplierId = @SupplierId
AND ScriptTypeId = @ScriptTypeId
AND SiteTypeId = @SiteTypeId
AND SiteName = @SiteName
AND HostName = @HostName
IF @@ROWCOUNT = 0
BEGIN
INSERT INTO HttpCallStatus_tbl (DayDate,SupplierId,GoodCalls,BadCalls,ScriptTypeId,SiteTypeId,TotalConnectionTime,
MaxWorkerThreads,MaxIOThreads,AvailWorkerThreads,AvailIOThreads,SiteName,HostName)
VALUES (CONVERT(DATETIME, getDate(), 103),
@SupplierId,
@GoodCalls,
@BadCalls,
@ScriptTypeId,
@SiteTypeId,
@ConnectionTime,
0,
0,
0,
0,
@SiteName,
@HostName)
END
表结构
Column_name Type Length
DayDate datetime 8
SupplierId int 4
GoodCalls int 4
BadCalls int 4
ScriptTypeId int 4
SiteTypeId varchar 50
TotalConnectionTime int 4
MaxWorkerThreads int 4
MaxIOThreads int 4
AvailWorkerThreads int 4
AvailIOThreads int 4
SiteName varchar 50
HostName varchar 50
SearchCount int 4
DomainId int 4
索引
[PK_HttpCallStatus_tbl] clustered, unique, primary key [DayDate],[SupplierId]
[IX_HttpCallStatus_tbl] nonclustered [SupplierId]
[idx_HttpCallStatus_tbl_1] nonclustered
[SupplierId], [ScriptTypeId], [SiteTypeId], [SiteName], [HostName]
, [DayDate], [GoodCalls], [BadCalls], [TotalConnectionTime]
我注意到这些变量是未使用的@MaxWorkerThreads、@MaxIOThreads、@AvailWorkerThreads、,
@可用线程。也可以使变量@goodcalls和@Badcalls变为TINYINTS。
我还注意到insert语句值(CONVERT(DATETIME,getDate(),103)中存在这种转换,但我认为这是默认值,因此可以更改为getDate()
我的问题是很难衡量这些改进,因为它们都很快,值得我做这些更改吗?我甚至会看到一点好处吗?我认为您在错误的地方进行了优化。您担心的是insert上一行的转换,而忽略了它前面where子句中的转换/函数。看起来假设您已将逻辑从标量函数移回where子句,这将有所帮助,但我将重点更改以下内容:
WHERE DATEADD(dd, 0, DATEDIFF(dd, 0, DayDate)) = DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
AND DATEPART(HOUR, DayDate) = DATEPART(HOUR, getDate())
看看可搜索性,找出一种方法来避免你的数据出现这种情况。这才是真正的收益所在
另外,在where子句中,只需检查所有其他条件是否具有相同的数据类型,以防止隐式转换。我认为您在错误的位置进行了优化。您担心的是insert上一行的转换,而忽略了它前面where子句中的转换/函数。看起来您移动了t他将逻辑从标量函数返回where子句,这将有所帮助,但我将重点更改以下内容:
WHERE DATEADD(dd, 0, DATEDIFF(dd, 0, DayDate)) = DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
AND DATEPART(HOUR, DayDate) = DATEPART(HOUR, getDate())
看看可搜索性,找出一种方法来避免你的数据出现这种情况。这才是真正的收益所在
另外,在where子句中,只需检查所有其他条件是否具有相同的数据类型,以防止隐式转换
[IX\u HttpCallStatus\u tbl]非聚集的[SupplierId]
它包含在[idx\u HttpCallStatus\u tbl\u 1]
中[GoodCalls]、[BadCalls]、[TotalConnectionTime]
DECLARE @MinDate DATETIME
DECLARE @MaxDate DATETIME
SET @MinDate=DATEADD(HOUR,DATEPART(HOUR, GETDATE()),CONVERT(DATETIME,CONVERT(VARCHAR,GETDATE(),101)))
SET @MaxDate=DATEADD(HOUR,1,@MinDate)
并更改要放置的位置的前两行
WHERE DayDate>=MinDate AND DayDate<MaxDate
其中DayDate>=MinDate和DayDate
删除索引[IX\u HttpCallStatus\u tbl]非聚集的[SupplierId]
它包含在[idx\u HttpCallStatus\u tbl\u 1]
中
将索引更改为非聚集的[SupplierId]、[ScriptTypeId]、[SiteTypeId]、[SiteName]、[HostName]、[DayDate]、[GoodCalls]、[BadCalls]、[TotalConnectionTime]
上的索引和列[GoodCalls]、[BadCalls]、[TotalConnectionTime]
就存储过程而言,我会在更新上面添加以下内容:
DECLARE @MinDate DATETIME
DECLARE @MaxDate DATETIME
SET @MinDate=DATEADD(HOUR,DATEPART(HOUR, GETDATE()),CONVERT(DATETIME,CONVERT(VARCHAR,GETDATE(),101)))
SET @MaxDate=DATEADD(HOUR,1,@MinDate)
并更改要放置的位置的前两行
WHERE DayDate>=MinDate AND DayDate<MaxDate
WHERE DayDate>=MinDate和DayDate尝试以下方法:
CREATE PROCEDURE [dbo].[mltHttpCallStatus]
@SupplierId AS INTEGER,
@CallIsGood AS BIT,
@MaxWorkerThreads AS INT,
@MaxIOThreads AS INT,
@AvailWorkerThreads AS INT,
@AvailIOThreads AS INT,
@ScriptTypeId AS INT,
@SiteTypeId AS VARCHAR(50),
@ConnectionTime AS INT,
@SiteName AS VARCHAR(50),
@HostName AS VARCHAR(50)
AS
--DEBUG BEN (Flight details keep failing) 07012008 19:30
--Return
SET NOCOUNT ON
DECLARE @GoodCalls AS INT,
@BadCalls AS INT,
@StartHour DateTime,
@EndHour DateTime
Select @StartHour = DATEADD(Hour, DATEDIFF(Hour, 0, GETDATE()), 0),
@EndHour = DATEADD(Hour, 1 + DATEDIFF(Hour, 0, GETDATE()), 0),
@BadCalls = 0,
@GoodCalls = 0
IF @CallIsGood = 1
SET @GoodCalls = 1
ELSE
SET @BadCalls = 1
UPDATE HttpCallStatus_tbl SET
GoodCalls = GoodCalls + @GoodCalls,
BadCalls = BadCalls + @BadCalls,
TotalConnectionTime = TotalConnectionTime + @ConnectionTime
--WHERE dbo.datepart_fn(DayDate) = dbo.datepart_fn(getDate())
WHERE DayDate >= @StartHour
And DayDate < @EndHour
AND SupplierId = @SupplierId
AND ScriptTypeId = @ScriptTypeId
AND SiteTypeId = @SiteTypeId
AND SiteName = @SiteName
AND HostName = @HostName
IF @@ROWCOUNT = 0
BEGIN
INSERT INTO HttpCallStatus_tbl (DayDate,SupplierId,GoodCalls,BadCalls,ScriptTypeId,SiteTypeId,TotalConnectionTime,
MaxWorkerThreads,MaxIOThreads,AvailWorkerThreads,AvailIOThreads,SiteName,HostName)
VALUES (CONVERT(DATETIME, getDate(), 103),
@SupplierId,
@GoodCalls,
@BadCalls,
@ScriptTypeId,
@SiteTypeId,
@ConnectionTime,
0,
0,
0,
0,
@SiteName,
@HostName)
END
创建过程[dbo]。[mltHttpCallStatus]
@供应商ID为整数,
@卡利斯古德一丝不苟,
@MaxWorkerThreads为INT,
@MaxIOThreads作为INT,
@AvailWorkerThreads为INT,
@可用线程为INT,
@ScriptTypeId为INT,
@SiteTypeId为VARCHAR(50),
@ConnectionTime为INT,
@站点名称为VARCHAR(50),
@主机名为VARCHAR(50)
作为
--调试本(航班详细信息持续失败)07012008 19:30
--返回
不计较
将@GoodCalls声明为INT,
@BadCalls作为INT,
@我们的日期时间,
@结束时间日期时间
选择@StartHour=DATEADD(Hour,DATEDIFF(Hour,0,GETDATE()),0),
@EndHour=DATEADD(Hour,1+DATEDIFF(Hour,0,GETDATE()),0),
@BadCalls=0,
@GoodCalls=0
如果@CallIsGood=1
设置@GoodCalls=1
其他的
设置@BadCalls=1
更新HttpCallStatus\u tbl集合
GoodCalls=GoodCalls+@GoodCalls,
BadCalls=BadCalls+@BadCalls,
TotalConnectionTime=TotalConnectionTime+@ConnectionTime
--其中dbo.datepart_fn(DayDate)=dbo.datepart_fn(getDate())
其中DayDate>=@StartHour
和DayDate<@EndHour
和SupplierId=@SupplierId
和ScriptTypeId=@ScriptTypeId
和SiteTypeId=@SiteTypeId
和SiteName=@SiteName
和HostName=@HostName
如果@@ROWCOUNT=0
开始
插入到HttpCallStatus_tbl(DayDate、SupplierId、GoodCalls、BadCalls、ScriptTypeId、SiteTypeId、TotalConnectionTime、,
MaxWorkerThreads、MaxIOThreads、AvailWorkerThreads、AvailIOThreads、SiteName、主机名)
值(转换(DATETIME,getDate(),103),
@供应商,
@再见,
@坏消息,
@脚本类型ID,
@SiteTypeId,
@连接时间,
0,
0,
0,
0,
@站点名称,
@主机名)
结束
请注意,我在查询之前计算了开始时间和结束时间,然后将其用作要搜索的日期范围。由于主键的第一列是DayDate,这将大大提高性能。尝试以下方法:
CREATE PROCEDURE [dbo].[mltHttpCallStatus]
@SupplierId AS INTEGER,
@CallIsGood AS BIT,
@MaxWorkerThreads AS INT,
@MaxIOThreads AS INT,
@AvailWorkerThreads AS INT,
@AvailIOThreads AS INT,
@ScriptTypeId AS INT,
@SiteTypeId AS VARCHAR(50),
@ConnectionTime AS INT,
@SiteName AS VARCHAR(50),
@HostName AS VARCHAR(50)
AS
--DEBUG BEN (Flight details keep failing) 07012008 19:30
--Return
SET NOCOUNT ON
DECLARE @GoodCalls AS INT,
@BadCalls AS INT,
@StartHour DateTime,
@EndHour DateTime
Select @StartHour = DATEADD(Hour, DATEDIFF(Hour, 0, GETDATE()), 0),
@EndHour = DATEADD(Hour, 1 + DATEDIFF(Hour, 0, GETDATE()), 0),
@BadCalls = 0,
@GoodCalls = 0
IF @CallIsGood = 1
SET @GoodCalls = 1
ELSE
SET @BadCalls = 1
UPDATE HttpCallStatus_tbl SET
GoodCalls = GoodCalls + @GoodCalls,
BadCalls = BadCalls + @BadCalls,
TotalConnectionTime = TotalConnectionTime + @ConnectionTime
--WHERE dbo.datepart_fn(DayDate) = dbo.datepart_fn(getDate())
WHERE DayDate >= @StartHour
And DayDate < @EndHour
AND SupplierId = @SupplierId
AND ScriptTypeId = @ScriptTypeId
AND SiteTypeId = @SiteTypeId
AND SiteName = @SiteName
AND HostName = @HostName
IF @@ROWCOUNT = 0
BEGIN
INSERT INTO HttpCallStatus_tbl (DayDate,SupplierId,GoodCalls,BadCalls,ScriptTypeId,SiteTypeId,TotalConnectionTime,
MaxWorkerThreads,MaxIOThreads,AvailWorkerThreads,AvailIOThreads,SiteName,HostName)
VALUES (CONVERT(DATETIME, getDate(), 103),
@SupplierId,
@GoodCalls,
@BadCalls,
@ScriptTypeId,
@SiteTypeId,
@ConnectionTime,
0,
0,
0,
0,
@SiteName,
@HostName)
END
创建过程[dbo]。[mltHttpCallStatus]
@供应商ID为整数,
@卡利斯古德一丝不苟,
@MaxWorkerThreads为INT,
@MaxIOThreads作为INT,
@AvailWorkerThreads为INT,
@有效面积
DayDate = CAST(GETDATE() AS DATE)