Perché le sequenze di Denali dovrebbero comportarsi meglio di colonne di identità?
-
16-10-2019 - |
Domanda
Nella sua risposta a Che è meglio :? colonne di identità o valori unici ID generato mrdenny dice:
Quando SQL Denali esce sosterrà sequenze che sarà più efficiente di identità, ma non si può creare qualcosa di più efficiente se stessi.
Io non sono così sicuro. Conoscendo Oracle di sequenze , ho sia per creare un trigger per l'inserimento, incapsulare ogni inserto in una chiamata di una stored procedure, o pregare che io non dimenticare di usare correttamente la sequenza quando faccio un Ad- hoc inserto.
dubito che i vantaggi di sequenze sono così evidenti.
Soluzione
Le rispondo anche qui. Ha a che fare con la struttura interna di come IDENTITY
e SEQUENCE
lavoro.
Con IDENTITY
, SQL Server pre-caches valori nella memoria in modo che siano facilmente disponibili. Vedi di Martin Smith risposta per i dettagli. Come vengono utilizzati i valori, un processo in background genera più valori. Come potete immaginare questo pool può esaurirsi abbastanza rapidamente, lasciando l'applicazione in balia del processo in background che genera i valori.
Con SEQUENCE
, SQL Server consente di definire la dimensione della cache dovrebbe essere. Mentre SQL Server in realtà non mantenere i valori nella cache, mantiene solo il valore attuale e il valore finale superiore, questo ridurrà notevolmente la quantità di IO che è necessario per creare valori.
Non impostare la cache di troppo in alto, in modo da ridurre il numero di numeri che possono essere utilizzati:. Se SQL Server dovesse bloccarsi, i valori specificati nel campo di cache corrente che non sono stati utilizzati sarebbe perduto
Come per l'inserimento fila, basta specificare un valore predefinito per la colonna, in questo modo:
DEFAULT (NEXT VALUE FOR Audit.EventCounter),
Altri suggerimenti
l'Itzik Ben Gan articolo è stato scritto la dimensione della cache hardcoded di 10 per IDENTITY
sembra essere stato modificato. Da i commenti su questo elemento di connessione
La dimensione della preassegnazione si basa sulla dimensione del tipo di dati della colonna proprietà identità è definita. Per uno SQL Server colonna integer, il server pre-alloca identità in intervalli da 1000 valori. Per i dati bigint digitare il server pre-alloca a intervalli di 10000 valori.
Il T-SQL Interrogazione libro contiene la seguente tabella, ma sottolinea che questi valori non sono documentati o garantiti per essere invariata.
+-----------------+-----------+
| DataType | CacheSize |
+-----------------+-----------+
| TinyInt | 10 |
| SmallInt | 100 |
| Int | 1,000 |
| BigInt, Numeric | 10,000 |
+-----------------+-----------+
L'articolo qui test varie cache di sequenza formati e dimensioni dei lotti di inserimento e viene fornito con i seguenti risultati.
Il che sembra dimostrare che per i grandi inserti IDENTITY
fuori effettua SEQUENCE
. Essa non prova la dimensione della cache 1.000 comunque e anche questi risultati sono solo un test. Guardando specificamente alle cache di dimensioni 1000 con i vari lotti di inserti ho ottenuto i seguenti risultati (cercando ogni dimensione del lotto 50 volte e aggregando i risultati come sotto- tutti i tempi in ms.)
+------------+-----------+-----------+-----------+-----------+-----------+-----------+
| | 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 lotto più grande di dimensioni la versione IDENTITY
sembra generalmente più veloce .
Il libro TSQL Interrogazione spiega anche perché IDENTITY
può avere un vantaggio di prestazioni rispetto sequenza.
Il IDENTITY
è specifica tabella e SEQUENCE
non lo è. Se il disastro è stato quello di colpire inserto metà prima che il buffer di registro è stato lavato non importa se il recuperato identità è un precedente uno come il processo di recupero sarà anche annullare l'inserimento, in modo da SQL Server non forza il lavaggio del buffer di log su ogni identità memorizzare nella cache correlato scrittura del disco. Tuttavia per la sequenza di questa è imposto come il valore potrebbe essere utilizzato per qualsiasi scopo - anche al di fuori del database. Così, nell'esempio di cui sopra con un milione di inserti e la dimensione della cache del 1000 questo è un ulteriore migliaio di vampate di log.
Script per 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;