Colonna anti-identità

6

Recentemente ho trovato un codice che genera un valore identità per una chiave:

DECLARE @ID INT;

SELECT @ID = MAX(ID) + 1 FROM Person;

INSERT INTO [Person]
    ([ID], [FirstName], [LastName])
VALUES
    (@ID, @FirstName, @LastName);

L'ho portato all'attenzione di un collega che sosteneva che non utilizzare un campo di incremento automatico incorporato è un approccio perfettamente ragionevole alla progettazione del database e in alcuni ambienti una best practice. Il razionale del collaboratore è che ti dà più controllo sui valori e ti consente di manipolare i dati più facilmente.

Potrei solo contrastare sottolineando che sembra semplicemente sciocco implementare la propria versione di una funzionalità supportata dal server. Ed è estremamente incline agli errori se qualcuno decide di utilizzare un metodo diverso per inserire un record.

Ci sono davvero dei buoni motivi per non usare una colonna Identity quando tutto ciò che serve è una chiave artificiale su un tavolo?

    
posta TGnat 08.07.2011 - 15:56
fonte

5 risposte

21

Non è necessario "discuterne". È necessario confrontarlo.

Il SELECT MAX() può essere molto, molto lento e potrebbe rallentare man mano che la tabella si ingrandisce. C'è poco da discutere una volta che hai misurazioni.

Inoltre, è molto probabile che si verifichi una condizione di competizione in cui due transazioni simultanee dovrebbero essere in grado di applicare lo stesso ID a un nuovo record. Un semplice test lo dimostrerà, anche

    
risposta data 08.07.2011 - 16:00
fonte
2

L'onere della prova della necessità del nuovo codice dovrebbe essere a carico di chi lo implementa.

Quando dici

I could only counter by pointing out that it just seems silly to do implement your own version of a feature that is supported by the server. And it is extremely error prone should someone decide to use a different method to insert a record.

chiedo, perché solo ? Secondo me, deve dimostrare che il guadagno presunto di "controllo e facilità di manipolazione" supera il tuo punto di semplicità. Di che controllo ha bisogno? Quali manipolazioni sono più facili?

Se non ha bisogno del controllo adesso , è un caso di "Non ne avrai ancora bisogno (ancora)"

    
risposta data 08.07.2011 - 16:29
fonte
2

Puoi anche correre in gare di dati con questo tipo di generazione del numero di sequenza. Basta un piccolo codice tra SELECT MAX (ID) e INSERT per consentire a una seconda istanza di un programma di selezionare lo stesso numero di ID "max" e usarlo, rovinando tutto.

Questo tipo di corsa ai dati può anche essere molto confuso, poiché la gente crede che funzioni a thread singolo. La convinzione prevale sulla realtà.

    
risposta data 08.07.2011 - 17:59
fonte
1

Se hai bisogno che la colonna Identity sia proprio quella, un modo per il 'database' di identificare in modo univoco i record, non c'è ragione per farlo da te ed è una cattiva scelta. Tuttavia, ci sono diverse domande sullo stackoverflow in cui una sorta di informazione aggiuntiva è allegata a questi valori.

Un esempio voleva reimpostare l'identità se un record è stato cancellato per evitare lacune nella sequenza. Ecco perché è meglio avere una colonna specifica per soddisfare questa esigenza. Se vuoi rianalizzare i valori, puoi farlo con il tuo codice personale e non rovinare l'identità. Ci sono alcune limitazioni di db e / o sviluppatore in cui vogliono sapere quale sarà l'identità prima che venga effettivamente creata. Vogliono avere una sorta di citazione sui loro documenti con questo numero e possono o non possono effettivamente inserire il record. Non capisco la necessità di questa regola aziendale, ma ancora una volta puoi avere una specifica colonna & codice che lo ospita senza interferire con un campo di identità integrato o con l'impostazione della chiave primaria.

Forse in queste circostanze questa è una configurazione comune. Ci sono quelli che sentono il bisogno di costruire l'intelligenza nelle loro chiavi. Non ne ho mai avuto bisogno. Un sacco di modi per controllare valori unici e sistemi di numerazione contorti.

    
risposta data 08.07.2011 - 16:36
fonte
1

Sembra che un caso di SELECT COUNT(1) FROM Foo sia più veloce di SELECT COUNT(*) FROM Foo . A meno che non si disponga di numeri reali per eseguire il backup, questa è solo una leggenda urbana o una preferenza personale. SELECT MAX() è in realtà ottimizzato , quindi potrebbe non esserci alcuna differenza di prestazioni tra l'utilizzo di questo e una sequenza Oracle o qualcosa del genere simile.

    
risposta data 08.07.2011 - 16:41
fonte

Leggi altre domande sui tag