web-dev-qa-db-ja.com

INNER JOINよりも速くテーブルを更新する

実行に7,387ミリ秒かかる内部結合を持つSQL Server 2012ストアドプロシージャがあります(アクティビティモニターで確認しました)。

[...]
declare @childrenIds as dbo.CodeIdList;

[...]
Update
    dbo.Code
set
    dbo.Code.CommissioningFlag = 21
From 
    dbo.Code
INNER JOIN
    @childrenIds c
ON
    dbo.Code.CodeId =  c.CodeId

CodeIdListは:

CREATE TYPE [dbo].[CodeIdList] AS TABLE (
    [CodeId] INT NULL
);

INNER JOINを使用するよりも速くコードテーブルを更新する方法はありますか?

私はdbaではないので、私の質問の詳細が必要かどうかはわかりません。必要な方はお問い合わせください。

コードテーブルでsp_helpindexを実行して、次の結果を得ました。

 index_name | index_description 
 PK_CODE |クラスタ化された一意の主キーがPRIMARYにあります。 CodeId 
 UC_CODE_SERIAL |非クラスター化された一意の一意のキーがPRIMARYにあります。シリアル

Codeテーブル作成スクリプト:

CREATE TABLE [dbo].[Code] (
    [CodeId]            INT            IDENTITY (1, 1) NOT NULL,
    [Serial]            NVARCHAR (20)  NOT NULL,
    [ ...]
    CONSTRAINT [PK_CODE] PRIMARY KEY CLUSTERED ([CodeId] ASC),
    CONSTRAINT [UC_CODE_SERIAL] UNIQUE NONCLUSTERED ([Serial] ASC)
)

現時点では、コードテーブルに1.006.896行あります。

実行計画:

enter image description here

http://Pastebin.com/9yXsRfva のXMLバージョン

SQL Serverのバージョン情報:

 Microsoft SQL Server Management Studio 11.0.6020.0 Herramientas cliente de Microsoft Analysis Services 11.0.6020.0 Microsoft Data Access Components(MDAC)6.1.7601.17514 
 Microsoft MSXML 3.0 4.0 6.0 
 Microsoft Internet Explorer 9.11.9600.18314 
 Microsoft .NET Framework 4.0.30319.42000 
 Sistema operativo 6.1.7601 

Select @@VERSION

 Microsoft SQL Server 2012(SP3)(KB3072779)-11.0.6020.0(X64)
 Oct 20 2015 15:36:27 
著作権(c)Microsoft Corporation Enterprise Edition(64 -bit)on 
 Windows NT 6.1(Build 7601:Service Pack 1)
2
VansFannel

私はこのインデックスを追加しました、そしてそれは結合を0ms平均持続時間にスピードアップしました:

CREATE INDEX [IDX_FLAG_LEVEL_CODE]
     ON Code (CommissioningFlag, AggregationLevelId)
     INCLUDE (Serial, CodeId);

前の質問 を解決しているときに、偶然に解決策を見つけました。

4
VansFannel

サービスパックレベルを指定しませんでしたが、チェックアウトすることをお勧めします this post Aaron Bertrandから、2012 Service Pack 2のトレースフラグについて ' might 'テーブル変数に対して結合するときのパフォーマンスを改善します。投稿によると:

「テーブル変数がSQL Serverの他のテーブルと結合されている場合、SQL Serverは統計をサポートしていないか、クエリプランのコンパイル中にテーブル変数内の行数を追跡しないため、非効率的なクエリプランの選択によりパフォーマンスが低下する可能性があります。」

さらに、テーブル変数の代わりに一時テーブルを使用すると違いが生じるかどうかを確認することは興味深いでしょう。

「実際の」実行プランのXMLを投稿すると、結合がどのように実行されているかについてより多くの情報が得られる場合があります。

2
Scott Hodgin

<> 21を追加して、すでに設定されているものをスキップできるようにします

Update dbo.Code
set    dbo.Code.CommissioningFlag = 21
From   dbo.Code
JOIN   @childrenIds c
ON     dbo.Code.CodeId =  c.CodeId 
where  dbo.Code.CommissioningFlag <> 21 or dbo.Code.CommissioningFlag is null

CodeIDがCodeIdListで一意である場合、それをPKとして宣言するとおそらく役立つ

1
paparazzo

UPDATEステートメント

UPDATE dbo.Code
SET dbo.Code.CommissioningFlag = 21
FROM dbo.Code
INNER JOIN @childrenIds c
ON dbo.Code.CodeId = c.CodeId;

@childrenIdsは一意であり、nullであってはならないことを示唆しています。

してみてください

DECLARE @childrenIds AS table ([CodeId] int PRIMARY KEY);

また、@childrenIdsにデータを入力するときは、この制約に注意してください(どの時点でも@childrenIdsに重複またはNULL CodeIdを挿入しないように注意してください)。

0
Y.B.