0

私は、以下のストアドプロシージャを微調整しようとしています。これは、当社のWebサイトで1分間に30k回呼び出されます。

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、@AvailIOThreadsであることに気付きました。また、変数@goodcallsと@BadcallsをTINYINTSにすることもできます。また、挿入ステートメントVALUES(CONVERT(DATETIME、getDate()、103)でこの変換に気づきましたが、これがデフォルトであるため、Getdate()に変更できます。

私の問題は、両方とも非常に迅速であるため、改善を測定するのが難しいです。これらの変更を行う価値はありますか?わずかな利益も見られますか?

4

4 に答える 4

2

間違った場所で最適化していると思います。その前にあるwhere句の変換/関数を無視しながら、挿入の1行の変換について心配しています。ロジックをスカラー関数からwhere句に戻したようですが、これは役に立ちますが、これを変更することに焦点を当てます。

WHERE DATEADD(dd, 0, DATEDIFF(dd, 0, DayDate)) = DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
        AND DATEPART(HOUR, DayDate) = DATEPART(HOUR, getDate()) 

インデックスで動作するものに。sargability http://en.wikipedia.org/wiki/Sargableを見て、データでこれを回避する方法を見つけてください。それが本当の利益になるところです。

また、where句では、暗黙の変換を防ぐために、他のすべての条件が同じデータ型であることを確認してください。

于 2013-01-08T12:59:41.407 に答える
2

これを試して:

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

クエリの前に開始時間と終了時間を計算し、それを検索する日付の範囲として使用していることに注意してください。主キーの最初の列はDayDateであるため、これによりパフォーマンスが大幅に向上するはずです。

于 2013-01-08T13:39:57.247 に答える
1
  1. インデックスを削除します [IX_HttpCallStatus_tbl] nonclustered [SupplierId]でカバーされてい [idx_HttpCallStatus_tbl_1]ます。
  2. [idx_HttpCallStatus_tbl_1] nonclustered [SupplierId], [ScriptTypeId], [SiteTypeId], [SiteName], [HostName], [DayDate], [GoodCalls], [BadCalls], [TotalConnectionTime] インデックスをインデックスに 変更し、[SupplierId], [ScriptTypeId], [SiteTypeId], [SiteName], [HostName], [DayDate] 含める [GoodCalls], [BadCalls], [TotalConnectionTime]

sprocに関する限り、更新の上にこれを追加します:

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 to beの最初の2行を変更します

WHERE  DayDate>=MinDate AND DayDate<MaxDate 
于 2013-01-08T13:37:28.633 に答える
1

いくつかのこと:

以下は、すべての挿入について GETDATE() を 'dd/mm/yyyy' (時間情報なし) に変換します。

CONVERT(DATETIME, getDate(), 103)

したがって、データ型を DATETIME ではなく DATE に変更できます。この変更により、次の項目を変更/削除できます。

CONVERT(DATETIME, getDate(), 103) 

Can change to:

CAST(GETDATE() AS DATE)

時間部分は保存されていないため、これはまとめて削除できます。

AND DATEPART(HOUR, DayDate) = DATEPART(HOUR, getDate()) 

これ

DATEADD(dd, 0, DATEDIFF(dd, 0, DayDate)) = DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))

次のように変更できます。

DayDate = CAST(GETDATE() AS DATE)

また、SQL サーバー 2008 以降を使用しているため、UPDATE/INSERT ロジックの代わりに MERGE を使用できます。

http://technet.microsoft.com/en-us/library/bb510625.aspx

于 2013-01-08T13:45:03.527 に答える