Dopo aver posto questa domanda confrontando i GUID sequenziali e non sequenziali, ho provato a confrontare le prestazioni INSERT su 1) una tabella con una chiave primaria GUID inizializzata in sequenza con newsequentialid()
e 2) una tabella con una chiave primaria INT inizializzata in sequenza con identity(1,1)
. Mi aspetto che quest'ultimo sia il più veloce a causa della minore larghezza degli interi, e sembra anche più semplice generare un numero intero sequenziale rispetto a un GUID sequenziale. Ma con mia sorpresa, gli INSERTI sulla tabella con il tasto intero erano significativamente più lenti della tabella GUID sequenziale.
Ciò mostra l'utilizzo del tempo medio (ms) per le esecuzioni del test:
NEWSEQUENTIALID() 1977
IDENTITY() 2223
Qualcuno può spiegare questo?
È stato utilizzato il seguente esperimento:
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
AGGIORNAMENTO: Modificando lo script per eseguire gli inserimenti basati su una tabella TEMP, come negli esempi di Phil Sandler, Mitch Wheat e Martin di seguito, trovo che l'IDENTITÀ sia più veloce di quanto dovrebbe essere. Ma questo non è il modo convenzionale di inserire righe, e ancora non capisco perché all'inizio l'esperimento sia andato storto: anche se ometto GETDATE () dal mio esempio originale, IDENTITY () è ancora molto più lento. Quindi sembra che l'unico modo per fare in modo che IDENTITY () superi NEWSEQUENTIALID () sia preparare le righe da inserire in una tabella temporanea ed eseguire i numerosi inserimenti come inserimento batch usando questa tabella temporanea. Tutto sommato, non credo che abbiamo trovato una spiegazione al fenomeno e IDENTITY () sembra essere ancora più lento per la maggior parte degli usi pratici. Qualcuno può spiegare questo?
INT IDENTITY
IDENTITY
non richiede un blocco della tabella. Concettualmente ho potuto vedere che potresti aspettarti che prenda MAX (id) + 1, ma in realtà viene memorizzato il valore successivo. In realtà dovrebbe essere più veloce di trovare il prossimo GUID.