Seit der Veröffentlichung des Artikels von Itzik Ben GanIDENTITY
scheint sich die fest codierte Cachegröße von 10 für geändert zu haben. Aus den Kommentaren zu diesem Verbindungselement
Die Größe der Vorbelegung basiert auf der Größe des Datentyps der Spalte, für die die Identitätseigenschaft definiert ist. Für eine SQL Server-Ganzzahlspalte weist der Server Identitäten in Bereichen von 1000 Werten vorab zu. Für den bigint-Datentyp weist der Server Bereiche von 10000 Werten vorab zu.
Das T-SQL-Abfragebuch enthält die folgende Tabelle, weist jedoch darauf hin, dass diese Werte nicht dokumentiert sind oder garantiert nicht geändert werden.
+-----------------+-----------+
| DataType | CacheSize |
+-----------------+-----------+
| TinyInt | 10 |
| SmallInt | 100 |
| Int | 1,000 |
| BigInt, Numeric | 10,000 |
+-----------------+-----------+
In diesem Artikel werden verschiedene Sequence-Cache-Größen und Insert-Batch-Größen getestet und die folgenden Ergebnisse erzielt.
Was zu zeigen scheint, dass bei großen Inserts IDENTITY
Out funktioniert SEQUENCE
. Die Cache-Größe 1.000 wird jedoch nicht getestet, und auch diese Ergebnisse sind nur ein Test. Bei genauerer Betrachtung der Cache-Größe 1.000 mit verschiedenen Stapelgrößen von Inserts ergaben sich die folgenden Ergebnisse (50-maliger Versuch jeder Stapelgröße und Aggregation der Ergebnisse wie folgt - alle Male 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 |
+------------+-----------+-----------+-----------+-----------+-----------+-----------+
Bei größeren Losgrößen erscheint die IDENTITY
Version in der Regel schneller .
Das Buch TSQL-Abfragen erläutert auch, warum IDENTITY
die Leistung gegenüber der Sequenz von Vorteil sein kann.
Das IDENTITY
ist tabellenspezifisch und SEQUENCE
nicht. Wenn die Katastrophe eine mittlere Einfügemarke war, bevor der Protokollpuffer geleert wurde, spielt es keine Rolle, ob die wiederhergestellte Identität eine frühere ist, da der Wiederherstellungsprozess auch die Einfügung rückgängig macht, sodass SQL Server das Leeren des Protokollpuffers nicht für jede Identität erzwingt Cache-bezogene Disc schreiben. Für Sequence wird dies jedoch erzwungen, da der Wert für jeden Zweck verwendet werden kann - auch außerhalb der Datenbank. Im obigen Beispiel mit einer Million Einfügungen und einer Cache-Größe von 1.000 sind dies zusätzliche tausend Protokolllöschungen.
Zu reproduzierendes Skript
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;