Da quando l'articolo Itzik Ben Gan è stato scritto, la dimensione della cache hardcoded di 10 per IDENTITY
sembra essere stata modificata. Dai commenti su questo elemento di connessione
La dimensione della pre-allocazione si basa sulla dimensione del tipo di dati della colonna su cui è definita la proprietà dell'identità. Per una colonna di numeri interi di SQL Server, il server pre-alloca le identità in intervalli di 1000 valori. Per il tipo di dati bigint il server pre-alloca in intervalli di 10000 valori.
Il libro delle query T-SQL contiene la seguente tabella ma sottolinea che questi valori non sono documentati o garantiti invariati.
+-----------------+-----------+
| DataType | CacheSize |
+-----------------+-----------+
| TinyInt | 10 |
| SmallInt | 100 |
| Int | 1,000 |
| BigInt, Numeric | 10,000 |
+-----------------+-----------+
L'articolo qui verifica varie dimensioni della cache di sequenza e inserisce le dimensioni del batch e fornisce i seguenti risultati.
Che sembra mostrare che per inserti di grandi dimensioni IDENTITY
esegue SEQUENCE
. Tuttavia, non verifica la dimensione della cache 1.000 e anche questi risultati sono solo un test. Osservando in particolare la dimensione della cache 1.000 con vari lotti di inserti ho ottenuto i seguenti risultati (provando ogni dimensione del lotto 50 volte e aggregando i risultati come sotto, tutti i tempi in μs).
+------------+-----------+-----------+-----------+-----------+-----------+-----------+
| | Sequence | Identity |
| Batch Size | Min | Max | Avg | Min | Max | Avg |
+------------+-----------+-----------+-----------+-----------+-----------+-----------+
| 10 | 2,994 | 7,004 | 4,002 | 3,001 | 7,005 | 4,022 |
| 100 | 3,997 | 5,005 | 4,218 | 4,001 | 5,010 | 4,238 |
| 1,000 | 6,001 | 19,013 | 7,221 | 5,982 | 8,006 | 6,709 |
| 10,000 | 26,999 | 33,022 | 28,645 | 24,015 | 34,022 | 26,114 |
| 100,000 | 189,126 | 293,340 | 205,968 | 165,109 | 234,156 | 173,391 |
| 1,000,000 | 2,208,952 | 2,344,689 | 2,269,297 | 2,058,377 | 2,191,465 | 2,098,552 |
+------------+-----------+-----------+-----------+-----------+-----------+-----------+
Per lotti di dimensioni maggiori, la IDENTITY
versione sembra generalmente più veloce .
Il libro di query TSQL spiega anche perché IDENTITY
può avere un vantaggio in termini di prestazioni rispetto alla sequenza.
È IDENTITY
una tabella specifica e SEQUENCE
non lo è. Se il disastro dovesse colpire l'inserimento intermedio prima che il buffer del log fosse scaricato, non importa se l'identità recuperata è precedente poiché anche il processo di ripristino annullerà l'inserimento, quindi SQL Server non forzerà lo svuotamento del buffer log su ogni identità scrittura su disco relativa alla cache. Tuttavia, per Sequence questo viene applicato in quanto il valore potrebbe essere utilizzato per qualsiasi scopo, anche al di fuori del database. Quindi nell'esempio sopra con un milione di inserimenti e una dimensione della cache di 1.000 si tratta di ulteriori mille flush di log.
Script da riprodurre
DECLARE @Results TABLE(
BatchCounter INT,
NumRows INT,
SequenceTime BIGINT,
IdTime BIGINT);
DECLARE @NumRows INT = 10,
@BatchCounter INT;
WHILE @NumRows <= 1000000
BEGIN
SET @BatchCounter = 0;
WHILE @BatchCounter <= 50
BEGIN
--Do inserts using Sequence
DECLARE @SequenceTimeStart DATETIME2(7) = SYSUTCDATETIME();
INSERT INTO dbo.t1_Seq1_cache_1000
(c1)
SELECT N
FROM [dbo].[TallyTable] (@NumRows)
OPTION (RECOMPILE);
DECLARE @SequenceTimeEnd DATETIME2(7) = SYSUTCDATETIME();
--Do inserts using IDENTITY
DECLARE @IdTimeStart DATETIME2(7) = SYSUTCDATETIME();
INSERT INTO dbo.t1_identity
(c1)
SELECT N
FROM [dbo].[TallyTable] (@NumRows)
OPTION (RECOMPILE);
DECLARE @IdTimeEnd DATETIME2(7) = SYSUTCDATETIME();
INSERT INTO @Results
SELECT @BatchCounter,
@NumRows,
DATEDIFF(MICROSECOND, @SequenceTimeStart, @SequenceTimeEnd) AS SequenceTime,
DATEDIFF(MICROSECOND, @IdTimeStart, @IdTimeEnd) AS IdTime;
TRUNCATE TABLE dbo.t1_identity;
TRUNCATE TABLE dbo.t1_Seq1_cache_1000;
SET @BatchCounter +=1;
END
SET @NumRows *= 10;
END
SELECT NumRows,
MIN(SequenceTime) AS MinSequenceTime,
MAX(SequenceTime) AS MaxSequenceTime,
AVG(SequenceTime) AS AvgSequenceTime,
MIN(IdTime) AS MinIdentityTime,
MAX(IdTime) AS MaxIdentityTime,
AVG(IdTime) AS AvgIdentityTime
FROM @Results
GROUP BY NumRows;