1250000レコード前後のテーブルと80列があります
テーブルの構造
CREATE TABLE [dbo].[Table] (
[Column1] [int] IDENTITY(1, 1) NOT FOR REPLICATION NOT NULL, [Column2] [int] NULL, [Column3] [int] NULL,
[Column4] [int] NULL, [Column5] [int] NULL, [Column6] [int] NULL, [Column7] [int] NULL, [Column8] [int] NULL,
[Column9] [int] NULL, [Column10] [varchar](20) NULL, [Column11] [datetime] NULL, [Column12] [int] NULL,
[Column13] [money] NULL, [Column14] [money] NULL, [Column15] [varchar](40) NULL, [Column16] [int] NULL,
[Column17] [int] NULL, [Column18] [varchar](20) NULL, [Column19] [varchar](50) NULL, [Column20] [int] NULL,
[Column21] [int] NULL, [Column22] [int] NULL, [Column23] [int] NULL, [Column24] [int] NULL,
[Column25Date] [datetime] NULL, [Column26] [int] NULL, [Column27] [int] NULL, [Column28] [int] NULL,
[Column29] [int] NULL, [Column30] [int] NULL, [Column75] [varchar](50) NULL, [Column31] [int] NULL,
[Column32] [varchar](15) NULL, [Column33] [int] NULL, [Column34] [money] NULL,
[Column35] [dbo].[T_Boolean2] NOT NULL, [Column36] [money] NULL, [Column37] [money] NULL,
[Column38] [int] NULL, [Column39] [int] NULL, [Column40] [varchar](255) NULL, [Column41PrintDate] [datetime] NULL,
[Column42PostDate] [datetime] NULL, [Column43FirstName] [varchar](30) NULL, [Column44LastName] [varchar](30) NULL,
[Column45Email] [varchar](50) NULL, [Column46PrimaryPhone] [varchar](10) NULL,
[Column47SecondaryPhone] [varchar](10) NULL, [Column48PrimaryPhoneType] [smallint] NULL,
[Column49SecondaryPhoneType] [smallint] NULL, [Column50PrimaryPhoneType] [smallint] NULL,
[Column51SecondaryPhoneType] [smallint] NULL, [Column52EndDate] [datetime] NULL,
[Column53] [dbo].[T_Boolean2] NOT NULL, [Column54] [int] NULL, [InsertTimeStamp] [datetime] NOT NULL,
[UpdateTimeStamp] [datetime] NULL, [Column55ID] [int] NULL, [Column56] [int] NULL, [Column57] [int] NULL,
[Column58] [int] NULL, [Column59] [money] NULL, [Column60] [money] NULL, [Column61] [money] NOT NULL,
[Column62] [money] NOT NULL, [Column63] [varchar](30) NULL, [Column64] [varchar](30) NULL,
[Column65] [varchar](10) NULL, [Column66] [varchar](6) NULL, [Column67] [varchar](10) NULL,
[Column68] [varchar](35) NULL, [Column69Date] [datetime] NULL, [Column70Date] [datetime] NULL,
[Column71Date] [datetime] NULL, [Column72] [varchar](255) NULL, [Column73PIN] [varchar](6) NULL,
[Column74Date] [datetime] NULL, [Column76Date] [datetime] NULL,
CONSTRAINT [XPKColumn1] PRIMARY KEY CLUSTERED (
[Column1] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]
2つの更新トリガーがあり、バックグラウンド計算を実行して、ステータスが変化したときやその他の条件が発生したときに同じテーブルを更新します
私が更新すると、1時間以上実行されているが、レコードを更新できなかった通常の場所の列が1つあるため、ステートメントを強制終了します
Update Table Column5 = 12345 where Column5 = 6789
約35000レコードを更新する必要があります
テーブルにはこの列の適切なインデックスがあり、手動でテーブルの統計を更新していますが、更新に時間がかかりすぎます
テーブルには約10のインデックスがあります
それから私はそれが更新された2つのバッチで更新しようとしましたが、非常に時間がかかりました
同じテーブルの他の列を更新しようとしましたが、更新に数秒かかりました
Update Table Column3 = 6789 where Column3 = 12345
更新ステートメントのクエリ速度を向上させ、上記の単純なロジックを使用する方法
解決策を提案してください、
前もって感謝します
トリガーのコードを確認せずに原因を正確に説明することは困難ですが、INSERTEDおよびDELETED仮想テーブルの誤用が原因であると考えられる、ゼロ以外の量はあると思います。
INSERTEDおよびDELETEDについてのことは、インデックスがないことです。それらを直接ベーステーブル(または相互に)に結合すると、非常にひどいパフォーマンスになる可能性があります。
通常、2つを一時テーブルにロードし、それらを結合する(通常は主キーで)ためのインデックスを作成することで、これを軽減できます。
SELECT *
INTO #i
FROM INSERTED
CREATE CLUSTERED INDEX CX_i ON #i (primary_key)
SELECT *
INTO #d
FROM DELETED
CREATE CLUSTERED INDEX CX_d ON #d (primary_key)
とにかく、そのようなもの。次に、一時テーブルのみを使用し、INSERTEDおよびDELETEDには触れないでください。
一時テーブル名はセッションごとに一意である必要があることに注意してください。カスケードする複数のトリガーがある場合、一意のテーブル名を使用する必要があります。これが問題になる場合は、代わりにテーブル変数を使用することをお勧めします。これらの変数は、実行中のトリガー/プロシージャにスコープが設定されており、名前の衝突のリスクがありません。 (ただし、テーブル変数にインデックスを付ける唯一の方法は、DECLARE
ステートメントでクラスター化された主キーを宣言することです。)
小さなグループでテーブルを更新することにより、更新操作のパフォーマンスを向上させることができます。
例を参照:
SET rowcount 10000
Update Table
Column3 = 6789
where Column3 = 12345
while @@rowcount>0
Update Table
Column3 = 6789
where Column3 = 12345
END
SET rowcount 0
上記のコードは一度に10000行を更新し、@@ rowcountの値がゼロになるまでループが続きます。これにより、テーブルがロックされなくなります。
SQL Serverで大きなテーブルを更新する際のベストプラクティス
別の追加-そして、これは少し複雑になるかもしれませんが、大きなテーブルを特定のフィールドでパーティション化してから、それらのパーティションを複数のディスクに分散するのが良い場合です。