Le migliori pratiche per generare nuovi identificatori per oggetti persistenti?

3

In uno scenario tipico, un oggetto che deve essere persistente nel database verrà creato nel codice dell'applicazione senza un identificatore e successivamente salvato in una tabella nel database. Alcuni costrutti di database, come una colonna Identity, genereranno un nuovo identificatore, tipicamente un intero che è unico per tutte le righe di quella tabella. Questo identificatore può quindi essere restituito al codice dell'applicazione e quindi trattato come una chiave.

CREATE TABLE Users (
    UserId int IDENTITY(1,1) NOT NULL, DisplayName nvarchar(max), 
    UserName nvarchar(50), [Password] nvarchar(50))
GO

INSERT INTO Users (DisplayName, UserName, [Password]) 
    VALUES ('Joe Shmo', 'jshmo', 'pw1')
SELECT @@IDENTITY

Un altro scenario comune è che l'identificatore sia GUID:

CREATE TABLE Users (
    UserId uniqueidentifier NOT NULL, DisplayName nvarchar(max), 
    UserName nvarchar(50), [Password] nvarchar(50))
GO

DECLARE @id uniqueidentifier = NEWID()
INSERT INTO Users (UserId, DisplayName, UserName, [Password]) 
    VALUES (@id, 'Joe Shmo', 'jshmo', 'pw1')
SELECT @id

Questo secondo modo offre il seguente vantaggio: il GUID può essere generato nel codice dell'applicazione, che può quindi essere utilizzato come chiave per scopi di caching / riferimento delle applicazioni prima che l'oggetto sia mai stato salvato. Tuttavia, vi è un costo associato all'utilizzo di GUID in termini di dimensioni e, in particolare, costi di ricerca. Questi possono essere banali quando il tavolo è piccolo, ma possono diventare un fattore importante quando il tavolo è enorme.

Esistono best practice o tecniche per i casi in cui un identificatore univoco per il tipo di oggetto deve essere generato nel codice dell'applicazione, ma non può essere un GUID per qualsiasi motivo?

Un pensiero era di avere un'altra tabella che genera un identificatore avvolto da un servizio identificatore che il codice dell'applicazione potrebbe chiamare.

    
posta afeygin 21.09.2011 - 21:32
fonte

5 risposte

4

entrambi gli approcci sono validi

se solo un server di database genera le chiavi, un ID di sequenza va bene, ed è (come hai notato) un po 'più efficiente (e molto più facile da leggere) di un GUID

se più server generano le chiavi, allora vai con un GUID

un'altra opzione è consentire al database di generare una chiave di sequenza per le relazioni interne e utilizzare un GUID come chiave secondaria univoca

come al solito, dipende da come crei e usi i dati

    
risposta data 21.09.2011 - 23:01
fonte
1

Una chiave primaria è implementata tramite un indice univoco. Per ottenere prestazioni ottimali, è necessario scegliere la lunghezza della colonna più piccola possibile e, se possibile, utilizzare il valore numerico. Questo ha un effetto sulle prestazioni nell'ordinamento e nella ricerca dei dati.

Il tipo di dati int di solito è abbastanza grande per la maggior parte delle applicazioni, ma potrebbe non essere nel tuo caso.

Uno svantaggio dei campi di identità è che se si usano numeri strettamente sequenziali, gli indici non vengono costruiti in modo efficiente, tuttavia, questo è davvero un problema minore. L'altra cosa stupida è che non è possibile visualizzare il valore della chiave prima di aver completato l'inserimento. Questo a volte può complicare la progettazione della GUI. Inoltre, è necessario utilizzare SCOPE_IDENTITY () per acquisire l'ultimo ID inserito che è un ulteriore lavoro per lo sviluppatore.

GUID è quasi universalmente unico, quindi sono più generici delle colonne di identità. Con GUID, la chiave è testo e è più grande del tipo int. È difficile da testare e difficile da fornire all'utente finale come parte di un'applicazione aziendale. Ad esempio, se utilizzato per il numero cliente, il numero di fattura, ecc. Diventa impraticabile e causa problemi all'utente finale. Anche i GUID non sono unici al 100%. Non conosco la probabilità esatta di duplicazione. L'unica cosa bella di loro è che possono essere generati sul client senza il round trip sul server.

La funzione NewID () e NewSequentialId () utilizza il GUID.

Puoi dare un'occhiata a questo per alcune informazioni: link

Se stai considerando un indice cluser, puoi controllare questo: link http://databases.aspfaq.com/database/what-should-i-choose-for-my-primary-key.html

    
risposta data 21.09.2011 - 23:39
fonte
1

Se vuoi usare un livello di persistenza come NHibernate, allora usare un Guid ha un vantaggio significativo su una colonna di identità: le Guid possono essere generate sul lato client non appena l'oggetto entità viene creato in memoria, senza colpire il database fare un inserto. Utilizzando una colonna Identity incrementale, devi inserire l'inserto per ottenere il tuo valore.

Questo è un vantaggio specifico del vantaggio generale di essere in grado di generare Id in modo distribuito che consenta a Guids. Se si intende avere qualsiasi tipo di dispositivo mobile, o database distribuiti, o solo la possibilità di importare in batch le righe, può essere molto utile generare nuovi Id senza colpire il database.

    
risposta data 22.09.2011 - 01:06
fonte
0

Conosco una tecnica chiamata Guid.Comb (vedi NHibernate) che presenta i vantaggi di un GUID, ma presenta alcune modifiche per evitare problemi di database. Il problema con GUID è che gli indici del database vengono frammentati a causa della loro natura casuale. Questo è un problema grave, soprattutto perché i GUID vengono spesso usati come chiavi primarie. Ma sappiate che non tutti gli algoritmi GUID soffrono di questo problema, come i produttori di database ne sono già a conoscenza. Non tutti i GUID sono intrinsecamente dannosi per la ricerca.

Ciò che fondamentalmente fai è creare un identificatore che elimina parte della casualità per ottenere un ordinamento nei GUID. Guarda questo articolo qui per avere un'idea di come può essere fatto.

Non vedo alcun motivo per non utilizzare GUID se non si incontrano problemi di spazio. Per i grandi volumi di dati questo può essere un problema molto, molto serio con impatti enormi.

Quando davvero non si può avere un GUID come PK, è possibile utilizzare un GUID come chiave secondaria, come già affermato da Steven A. Lowe.

    
risposta data 21.09.2011 - 23:07
fonte
0

O uno è OK a seconda delle tue esigenze. Con una colonna di identità intera esiste un valore che richiede poca manutenzione con la colonna nel tempo poiché i dati sull'indice sono sequenziali. È possibile inserire 1000 e 1000 di righe e l'indice sulla colonna sarà difficilmente frammentato.

Con un GUID, l'indice si frammenterà nel tempo e la manutenzione periodica (ricostruzione dell'indice, ecc.) dovrà essere eseguita per mantenere l'indice sulla colonna chiave. Quindi, finché ne sei a conoscenza, credo che entrambi siano OK.

Gli interi occupano meno spazio ma sono più facili da indovinare, i guids occupano più spazio e sono più difficili da indovinare. Come hai detto, i GUID possono essere generati nel codice, sebbene SQL Server possa fare anche una colonna identity o newID (). Credo anche che ci sia qualcosa chiamato guida sequenziale che aiuta nel dipartimento di frammentazione.

Se dovessi mai unire due database insieme, i guidi sarebbero migliori in quanto gli ID di riga si collocherebbero probabilmente tra i due database.

    
risposta data 21.09.2011 - 23:09
fonte

Leggi altre domande sui tag