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.

È stato utile?

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.

entrare descrizione dell'immagine qui

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;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a dba.stackexchange
scroll top