SQL Server: NEWID versus NEWSEQUENTIALID

SQL Server: NEWID versus NEWSEQUENTIALID

In SQL Server abbiamo la possibilita’ di definire un campo come UNIQUEIDENTIFIER e sappiamo benissimo tutti che a questa tipologia di campo corrisponde una GUID come valore consentito.

Nel corso di questo breve contenuto desidero mostrarvi un TIPS per migliorare le performance in SQL Server quando si sfruttano tabelle con una Primary KEY contenente una Guid.

Veniamo al punto principale Che differenza abbiamo tra le due parole chiave?

  • NEWID: Genera una nuova guid in maniera casuale
  • NEWSEQUENTIALID: Genera una nuova guid in maniera sequenziale

Ora basta parole e passiamo a vedere qualche script SQL Server

Creazione Tabella

Per comodita’ (e pigrizia) riprendo lo script scritto nel post “T-SQL: OUTPUT Clause INSERTED” nel mese di gennaio ripulendolo dal superfluo.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
CREATE TABLE [dbo].[mail_key_guid](
	[Id] [uniqueidentifier] NOT NULL,
	[email] [nchar](200) NULL,
 CONSTRAINT [PK_mail_key_guid] PRIMARY KEY CLUSTERED 
(
	[Id] ASC
)WITH 
    (
        PAD_INDEX = OFF, 
        STATISTICS_NORECOMPUTE = OFF, 
        IGNORE_DUP_KEY = OFF, 
        ALLOW_ROW_LOCKS = ON, 
        ALLOW_PAGE_LOCKS = ON, 
        OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF
    ) ON [PRIMARY]
) ON [PRIMARY]
GO

Ora che abbiamo la nostra tabella, possiamo entrare nel vivo dell’articolo.

NEWID

Ammettiamo di volere cambiare la definizione della precedente tabella assegnando il valore NEWID() al campo [Id] se non specificato nella query di INSERT.

1
2
3
4
ALTER TABLE [dbo].[mail_key_guid]
    ADD  CONSTRAINT [DF_mail_key_guid_Id]  
    DEFAULT (newid()) FOR [Id]
GO

Sino a qua e’ semplice, vero?

NEWSEQUENTIALID

Facendo finta di non avere definito il precedente DF_mail_key_guid_Id rilanciamo lo script con la seguente modifica

1
2
3
4
ALTER TABLE [dbo].[mail_key_guid]
    ADD  CONSTRAINT [DF_mail_key_guid_Id]  
    DEFAULT (NEWSEQUENTIALID()) FOR [Id]
GO

NEWID Vs. NEWSEQUENTIALID

Provero’ ad analizzare il punto interessante tramite due query di INSERT

1
INSERT INTO [dbo].[mail_key_guid](email) VALUES('...')

oppure

1
2
INSERT INTO [dbo].[mail_key_guid](Id,email)     
    SELECT NEWID(), [my_email] FROM [dbo].[mail_backup]

oppure

1
2
INSERT INTO [dbo].[mail_key_guid](email) 
    SELECT [my_email] FROM [dbo].[mail_backup]

Avrete gia’ visto N mila volte questo esempio, vero?

Tips:

Vi ricordo che non e’ possibile effettuare

1
SELECT NEWSEQUENTIALID(), [my_email] FROM [dbo].[mail_backup]

L’unico modo per utilizzarlo e’ di metterlo come valore di default nel campo uniqueidentifier definito come Primary KEY.

Analisi Data

Ora vi mostro un esempio pratico come appariranno i valori della colonna Id (chiave primaria) usando i due differenti valori di default

NEWIDNEWSEQUENTIALID
C493C8AF-78F5-453C-9520-7948F15188ED7AC1D89D-118C-EB11-93D0-4074E07192DC
1334D1A2-059B-4902-A5A4-8819DA4797157BC1D89D-118C-EB11-93D0-4074E07192DC
515F0F83-C447-43E6-8AF4-E349AE9D42B97CC1D89D-118C-EB11-93D0-4074E07192DC
E5E0319A-BCA8-491B-B59A-37D19BA9FA647DC1D89D-118C-EB11-93D0-4074E07192DC
79EC038F-6B5F-4D64-A56D-8A9E8D86E85C7EC1D89D-118C-EB11-93D0-4074E07192DC
84D86E7B-54BA-4BA9-81AF-B53292A85D6EC3B53C6E-128C-EB11-93D0-4074E07192DC
EAE477C3-43E0-4C21-B2A3-06D73A4677B8C4B53C6E-128C-EB11-93D0-4074E07192DC
A504AACC-4C62-4BCD-B187-BAD4B1BF2C8BBE11947C-128C-EB11-93D0-4074E07192DC
F997B6D3-4BE2-4A69-AA28-A23123F5EEEDBF11947C-128C-EB11-93D0-4074E07192DC
AE446DAF-C0F5-4248-A293-B2D739582C22C011947C-128C-EB11-93D0-4074E07192DC
353E2682-3CDA-49B6-84D6-17EED5DE4354C111947C-128C-EB11-93D0-4074E07192DC
C3E2E5FE-B138-421E-9413-F9B7B8977BA0C211947C-128C-EB11-93D0-4074E07192DC
ACA16889-D855-4F90-AB33-658F2F69192DC311947C-128C-EB11-93D0-4074E07192DC
6A42D99D-4E96-4A02-9B07-9143CD15BE5EC411947C-128C-EB11-93D0-4074E07192DC

Vantaggio NEWSEQUENTIALID

Come avrete notato ad occhio le chiavi inserire col default NEWSEQUENTIALID() sono ordinate e -volendo- si possono anche identificare i blocchi/momenti in cui sono state inserite nella tabella guardando la somiglianza delle Guid.

DOMANDA: Ho capito ed ho visto la differenza tra le due, ma che vantaggio ottengo usando NEWSEQUENTIALID()?

PERFORMANCE TIPS: La risposta e’ molto semplice. Il guadagno lo otteniamo in performance soprattutto nelle operazioni di INSERT dove sono coinvolti un gran numero di record. Inoltre eventuali indici sul campo vi ringrazieranno non dovendo ricostruire pesantemente la tabella.

Fidatevi, ho avuto esperienze con una tabella da milioni di record inseriti con NEWID() ed indici distrutti da dovere ricostruire ogni notte.

Le operazioni di INSERT erano veramente lunghe e processi massivi diventavano estenuanti.

Passando a soluzioni con Guid sequenziali il vantaggio e’ stato impressionante riducendo sia i tempi di esecuzione dei processi, che di ricostruzione indici.

Non mi credi? Buon divertimento ….

In questi giorni ho utilizzato questa tecnica per travasare circa un 50K records tramite il Copy Data di Azure Data Factory. Il mapping e’ stato effettuato su tutti i campi tranne uno.

Indovinate quale?