Po zadaniu tego pytania porównując sekwencyjne i niesekwencyjne identyfikatory GUID, próbowałem porównać wydajność INSERT na 1) tabeli z kluczem podstawowym GUID inicjowanym sekwencyjnie newsequentialid()
, oraz 2) tabeli z kluczem podstawowym INT inicjowanym sekwencyjnie identity(1,1)
. Spodziewałbym się, że ta ostatnia będzie najszybsza z powodu mniejszej szerokości liczb całkowitych, a także wydaje się łatwiejsze wygenerowanie sekwencyjnej liczby całkowitej niż sekwencyjny identyfikator GUID. Ale ku mojemu zdziwieniu, WSTAWKI na stole z kluczem całkowitym były znacznie wolniejsze niż sekwencyjna tabela GUID.
To pokazuje średni czas użycia (ms) dla testów:
NEWSEQUENTIALID() 1977
IDENTITY() 2223
Czy ktoś może to wyjaśnić?
Zastosowano następujący eksperyment:
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
AKTUALIZACJA: Modyfikując skrypt w celu wykonywania wstawień w oparciu o tabelę TEMP, jak w przykładach autorstwa Phila Sandlera, Mitcha Wheata i Martina poniżej, stwierdzam również, że TOŻSAMOŚĆ jest szybsza, jak powinna. Ale to nie jest konwencjonalny sposób wstawiania wierszy i nadal nie rozumiem, dlaczego eksperyment zawiódł na początku: nawet jeśli pominę GETDATE () w moim oryginalnym przykładzie, TOŻSAMOŚĆ () jest nadal znacznie wolniejsza. Wydaje się więc, że jedynym sposobem na osiągnięcie lepszej wydajności IDENTITY () NEWSEQUENTIALID () jest przygotowanie wierszy do wstawienia do tabeli tymczasowej i wykonanie wielu wstawień jako wsadowego wsadu przy użyciu tej tabeli temp. Podsumowując, nie sądzę, że znaleźliśmy wyjaśnienie tego zjawiska, a TOŻSAMOŚĆ () wydaje się być wolniejsza w przypadku większości praktycznych zastosowań. Czy ktoś może to wyjaśnić?
INT IDENTITY
IDENTITY
nie wymaga blokady stołu. Pod względem koncepcyjnym widziałem, że możesz oczekiwać, że zajmie MAX (id) + 1, ale w rzeczywistości kolejna wartość jest przechowywana. Powinno to faktycznie być szybsze niż znalezienie następnego identyfikatora GUID.