求めた後、このシーケンシャルおよび非シーケンシャルGUIDを比較する質問を、私はGUID主キーを持つテーブルがで順次初期化)1上のINSERTのパフォーマンスを比較してみましたnewsequentialid()
主キーがで順次初期化INTと、および2)テーブルidentity(1,1)
。整数の幅が小さいため、後者の方が高速であると予想されます。また、順次GUIDよりも順次整数を生成する方が簡単だと思われます。しかし、驚いたことに、整数キーを持つテーブルでのINSERTは、シーケンシャルGUIDテーブルよりも大幅に遅くなりました。
これは、テスト実行の平均時間使用量(ミリ秒)を示します。
NEWSEQUENTIALID() 1977
IDENTITY() 2223
誰でもこれを説明できますか?
次の実験が使用されました。
SET NOCOUNT ON
CREATE TABLE TestGuid2 (Id UNIQUEIDENTIFIER NOT NULL DEFAULT NEWSEQUENTIALID() PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))
CREATE TABLE TestInt (Id Int NOT NULL identity(1,1) PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))
DECLARE @BatchCounter INT = 1
DECLARE @Numrows INT = 100000
WHILE (@BatchCounter <= 20)
BEGIN
BEGIN TRAN
DECLARE @LocalCounter INT = 0
WHILE (@LocalCounter <= @NumRows)
BEGIN
INSERT TestGuid2 (SomeDate,batchNumber) VALUES (GETDATE(),@BatchCounter)
SET @LocalCounter +=1
END
SET @LocalCounter = 0
WHILE (@LocalCounter <= @NumRows)
BEGIN
INSERT TestInt (SomeDate,batchNumber) VALUES (GETDATE(),@BatchCounter)
SET @LocalCounter +=1
END
SET @BatchCounter +=1
COMMIT
END
DBCC showcontig ('TestGuid2') WITH tableresults
DBCC showcontig ('TestInt') WITH tableresults
SELECT batchNumber,DATEDIFF(ms,MIN(SomeDate),MAX(SomeDate)) AS [NEWSEQUENTIALID()]
FROM TestGuid2
GROUP BY batchNumber
SELECT batchNumber,DATEDIFF(ms,MIN(SomeDate),MAX(SomeDate)) AS [IDENTITY()]
FROM TestInt
GROUP BY batchNumber
DROP TABLE TestGuid2
DROP TABLE TestInt
更新: 以下のPhil Sandler、Mitch Wheat、Martinの例のように、TEMPテーブルに基づいて挿入を実行するようにスクリプトを変更すると、IDENTITYのほうが高速になります。しかし、これは行を挿入する従来の方法ではなく、最初に実験が失敗した理由はまだわかりません。元の例からGETDATE()を省略しても、IDENTITY()の方がずっと遅いです。したがって、IDENTITY()がNEWSEQUENTIALID()よりも優れている唯一の方法は、一時テーブルに挿入する行を準備し、この一時テーブルを使用してバッチ挿入として多くの挿入を実行することです。全体として、私は現象の説明を見つけたとは思わず、IDENTITY()はほとんどの実用的な使用法でまだ遅いようです。誰でもこれを説明できますか?
IDENTITY
は、テーブルロックは必要ありません。概念的には、MAX(id)+ 1をとると予想されるかもしれませんが、実際には次の値が格納されます。実際には、次のGUIDを見つけるよりも速いはずです。