Perché IDENTITY_INSERT ON è consentito solo su una tabella alla volta?


20

È possibile che IDENTITY_INSERT possa essere impostato su ON in una tabella di database alla volta, ma perché? Dal momento che le IDENTITYcolonne non sono univoche a livello globale, non riesco a pensare a nessuna situazione pericolosa che potrebbe essere causata dall'inserimento di identità in più di una tabella contemporaneamente (almeno non più pericolosa di quella che generalmente si confonde con IDENTITY INSERT).

IDENTITY INSERT dovrebbe essere usato raramente, ma qual è il motivo del limite rigido?


1
Deterrente forse, quindi viene usato raramente?
Remus Rusanu,

@RemusRusanu è un po 'quello che stavo pensando, o quello o per assicurarmi di non lasciare accidentalmente II ON su più tavoli.
Ben Brocka,

@Ben perché lasciarlo accidentale accidentalmente per più tavoli è peggio che lasciarlo accidentale accidentalmente per un tavolo? Entrambi possono portare allo stesso tipo di problema. Sono sinceramente curioso della tua domanda e non credo che il deterrente sia la risposta, o avremmo molte più restrizioni nel motore. Ma sono d'accordo sul fatto che se ritieni di doverlo fare spesso, probabilmente c'è qualcosa di sospetto.
Aaron Bertrand

@AaronBertrand non lo è, come ho sottinteso nel Q. Non sono sicuro del deterrente, dal momento che SQL Server consente molte altre cattive pratiche come nominare le tue colonne con parole chiave riservate (a volte anche se non usi []!)
Ben Brocka

@Ben giusto che non era necessariamente per te ma per tutti i lettori che si sono imbattuti nella domanda.
Aaron Bertrand

Risposte:


12

Penso che sia per renderlo difficile. Se potessi lasciarlo sempre acceso, perché anche avere un campo identità?

In realtà ci sono un paio di restrizioni:

  • Persiste solo su quella connessione
  • È impostabile solo su una tabella per connessione

Sulla base delle restrizioni relative alla connessione, penso che sia principalmente quindi non è mai accidentalmente lasciato acceso.

Immagina se qualcuno attivasse l'inserimento ID su una delle tue tabelle, quindi non ti rendessi conto e fosse stato eseguito un inserimento (normalmente) non valido che ha rotto l'integrità del campo ID?

Ricorda che i campi ID possono avere valori duplicati se non sono presenti vincoli o indici univoci in atto ...


1
+1 Penso che il tuo ultimo punto sui duplicati sia mancato di molto. La gente pensa che se lo imposta IDENTITYdiventa anche un vincolo unico. Molto facile da confutare, ovviamente, se ci provano.
Aaron Bertrand

@AaronBertrand Ma ancora una volta, il rischio ID duplicato è esattamente lo stesso su qualsiasi tabella con IDENTITY INSERT attivato, perché il limite rigido? Penso che il fatto che persista solo per la connessione ha molto più senso come precauzione.
Ben Brocka,

Non stavo suggerendo che il problema dell'ID duplicato fosse una ragione del limite rigido.
Aaron Bertrand

6

La mia ipotesi è che è stata una restrizione a causa dell'implementazione. Consentire questa impostazione su più tabelle è stato un potenziale successo di prestazione:

Poiché si tratta di un parametro di sessione, consentire l'impostazione dell'attivazione su una singola tabella significa che si tratta di un flag semplice e dell'ID oggetto della tabella da archiviare nella sessione, sul lato server. Forse questo è solo un singolo numero intero: 0 se nessun IDENTITY_INSERT è attivo e alcuni codici di databaseid + objectid per la tabella.

Consentire l'impostazione del parametro su più tabelle all'interno di una sessione significherebbe che il server memorizzerà un elenco dinamico di tali oggetti e lo controllerebbe per ogni istruzione di inserimento. Immagina che una sessione attivi il parametro per mille tabelle:

  1. Ciò significa che il server ha allocato 1000 elementi nella variabile di sessione
  2. Ciò significa anche che il server deve controllare l'elenco dei 1000 elementi per ogni istruzione di inserimento in questa sessione.

Inoltre, ho il sospetto che il set di identity_insert abbia un impatto prestazionale sul server. In sybase esisteva un " fattore di impostazione della masterizzazione dell'identità ", che consentiva di salvare il valore del contatore di identità di una tabella da salvare solo una volta ogni tanto (il valore viene tenuto in memoria e annotato sul disco una volta ogni tanto e sul server spegnimento ). SQL Server si basa sullo stesso codice, quindi probabilmente ha un'ottimizzazione comparabile, ma l'attivazione di identity_insert su una tabella probabilmente vincola il server a salvare il valore di identità per ogni inserimento, perché altrimenti non può garantire una dimensione massima del gap. Quindi, se una sessione ha un impatto sulle prestazioni degli inserti in una tabella, questo è probabilmente accettabile, ma non se può fare il colpo perfetto su tutte le tabelle di auto_increment sul server.


+1 Probabilmente un po 'di verità qui. Non compro l'argomento della dimensione del divario, poiché solo una INSERTpuò essere eseguita alla volta per una sessione e potrei facilmente inserire 10 milioni di IDENTITYvalori codificati .
Aaron Bertrand

La dimensione del gap è correlata a ciò che accade in caso di crash: su Sybase, se il server si arresta in modo anomalo, l'ultima identità viene persa (era in memoria), quindi si riavvia lasciando un gap (vedere il fattore di impostazione della masterizzazione dell'identità)
Olivier S

Quindi in SQL Server stai suggerendo che succede qualcosa di diverso se il motore si arresta in modo anomalo durante l'inserimento di 1.000.000 di righe con una colonna di identità o sovrascrivendo la colonna di identità con 1.000.000 di valori codificati mentre SET IDENTITY_INSERTè abilitato? Sto solo suggerendo che la dimensione del gap non influisce su più tabelle in modo diverso rispetto a una singola tabella.
Aaron Bertrand

la mia ipotesi - non ne ho assolutamente alcuna prova - è che SET IDENTITY_INSERT su una tabella forza una scrittura su disco dell'autoincremento ad ogni inserto. La logica sarebbe che dato che il valore inserito può essere qualsiasi cosa, il server non può considerare "ok, se scrivo sul disco solo una volta ogni 1000 righe, in caso di crash posso tranquillamente aggiungere 1000 all'ultimo valore che ho salvato"
Olivier S,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.