Colonna identity

sabato 17 marzo 2012 - 15.57
Tag Elenco Tags  SQL Server 2008 R2  |  SQL Server 2008

andrestu Profilo | Expert

volevo sapere se si può fare in modo che una colonna impostata come identity alla fine del ciclio rincomincia dal primo numero libero. Mi spiego meglio.
Ho impostato una colonna come tinyint e gli ho impostato l'identity con incremento di 1. dopo 256 record inseriti ovviamente non ne posso più inserire, a questo punto vorrei che cancellando un record mi rendesse disponibile il numero identiti liberato avendo quindi la possibilità di inserirne uno, è possibile?




Andrea Restucci - Web Developer

alx_81 Profilo | Guru

>Ho impostato una colonna come tinyint e gli ho impostato l'identity
>con incremento di 1. dopo 256 record inseriti ovviamente non
>ne posso più inserire, a questo punto vorrei che cancellando
>un record mi rendesse disponibile il numero identiti liberato
>avendo quindi la possibilità di inserirne uno, è possibile?
l'identità, in quanto tale, auto incrementa del passo che hai dato tu, senza MAI tornare indietro.
C'è tuttavia una funzione per fare il reseed via Database Console Command (DBCC CHECKIDENT('<schema.nometab>', RESEED, <valore da cui vuoi partire - 1>).
Attenzione però, perchè va bene solo per casi di emergenza. Anche perchè facendo reseed non c'è nulla che poi impedirà all'identità di saltare i valori già usati.
Non capisco però perchè vuoi dare tanta importanza ad un valore che di solito corrisponde ad una chiave che non vuoi mostrare..
Non puoi ampliare il campo e andare avanti semplicemente?
Diciamo che l'identità non è fatta per una gestione dinamica dei valori..
--
Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi

andrestu Profilo | Expert

bè è per fare un ottimizzazione in un contesto di grande quantità di record, ti spiego brevemente facendo un esempio:

ho una tabella tableMaster con le seguenti colonne:
ID IDtableA(chiave secondaria) IDtableB(chiave secondaria) IDtableC(chiave secondaria) ... (fino a 30 colonne circa)

e ovviamente le corrispondenti tabelle collegate:
tableA - tableB - tableC ...
con le relative chiavi primarie.

In un ottica di grande quantità di record contenuti nella tabella tableMaster e pochissima quantità di record nelle altre tabelle dove oltretutto gli aggiornamenti (inserimenti ed eliminazioni) saranno pochissimi (forse nulli) ho pensato che sarebbe meglio attribuire alle colonne relative alle chiavi primarie/secondarie un tipo tinyint invece che int.
Considerando anche che questi tipi verranno mappati a collection residenti in memoria ecco che avrei per ogni chiave un tipo byte al posto di un int, il che in un contesto dove in memoria vengono manipolate queste collection da diversi utenti contemporaneamente ecco che allora la cosa potrebbe avere senso al fine di ottimizzare la quantità di dati occupata.
A questo punto rimarrebbe un questione da risolvere:
ammettiamo il caso in cui (casistica molto improbabile) venissero inseriti più di 255(grandezza max del tinyint) record su una delle tabelle in questione come si potrebbe risolvere?
ecco che qui tornava utile fare in modo che l'identity rincominciasse dal primo unmero disponibile.
Ho risolto disattivando l'identity sulle colonne relative alle chiavi primarie e sostituire il meccanismo dell'identity con un meccanismo manuale e cioè ad ogni inserimento rilevo tramite SP il primo numero disponibile libero.
Si lo so è un modo un pò anomalo per gestire queste tabelle ma in un ottica di super ottimizzazione...
cosa ne pensi? ho esagerato? ho fatto una grande cagata?






Andrea Restucci - Web Developer

alx_81 Profilo | Guru

>In un ottica di grande quantità di record contenuti nella tabella
>tableMaster e pochissima quantità di record nelle altre tabelle
>dove oltretutto gli aggiornamenti (inserimenti ed eliminazioni)
>saranno pochissimi (forse nulli) ho pensato che sarebbe meglio
>attribuire alle colonne relative alle chiavi primarie/secondarie
>un tipo tinyint invece che int.
a parte che puoi dimezzare l'int con degli smallint che comunque sono a due byte invece che quattro.
Capisco che usare tinyint ti consenta di risparmiare sia in termini di I/O che di spazio.
Ma tu stai parlando del valore del campo, che hai impostato per scelta ad Identità, che, per definizione, è readonly.
Intervenire su un campo readonly non mi sembra corretto. Piuttosto vedi tu se vuoi riempire gli spazi lasciati vuoti con un algoritmo tuo (che simula un'identità dandoti il primo valore saltato).
Però sinceramente lo sforzo applicativo mi sembra troppo elevato per giustificare l'utilizzo di un tipo di dato più grande.
Ma sai già a priori se supererai il massimo dei record consentiti? Se sì, perdonami, ma il tipo di dato è sbagliato in analisi, dovresti assegnare "il più piccolo tipo di dati per il più grande dei valori che otterrai".
Quindi, mi viene da consigliarti l'utilizzo del tipo più corposo, senza sfociare nell'int.

>Considerando anche che questi tipi verranno mappati a collection
>residenti in memoria ecco che avrei per ogni chiave un tipo byte
>al posto di un int, il che in un contesto dove in memoria vengono
>manipolate queste collection da diversi utenti contemporaneamente
>ecco che allora la cosa potrebbe avere senso al fine di ottimizzare
>la quantità di dati occupata.
certo, ma continuo a pensare che lo sforzo applicativo non vale quanto l'usare uno short (int16).

>A questo punto rimarrebbe un questione da risolvere:
>ammettiamo il caso in cui (casistica molto improbabile) venissero
>inseriti più di 255(grandezza max del tinyint) record su una
>delle tabelle in questione come si potrebbe risolvere?
appunto ampliando il tipo, questione di analisi. E va fatta il più possibile a priori.

>ecco che qui tornava utile fare in modo che l'identity rincominciasse dal primo unmero disponibile.
troppo spreco di risorse in fase di inserimento o update, dovresti ogni volta controllare il primo buco con letture inutili, settare l'identity_insert a on, "reseedare" (passamela), inserire..
Direi di no, tipo più corposo ancora. Anche perchè, pensa a tutti quei record che si legano a quell'id (che potrebbero non avere Foreign Key) o quelli "storicizzati", che legame avrebbero? Un record aveva un id una volta, poi quell'id è stato usato da altri.. Se vuoi ricostruire una storia? Eviterei questo tipo di approccio.
Piuttosto pensa a lavorare con insiemi piccoli, indicizzare, fare tuning delle chiamate, quello migliora le performances.

>Ho risolto disattivando l'identity sulle colonne relative alle
>chiavi primarie e sostituire il meccanismo dell'identity con
>un meccanismo manuale e cioè ad ogni inserimento rilevo tramite
>SP il primo numero disponibile libero.
>Si lo so è un modo un pò anomalo per gestire queste tabelle ma
>in un ottica di super ottimizzazione...
>cosa ne pensi? ho esagerato? ho fatto una grande cagata?
rispondevo mentre leggevo.. direi che senza volere ho detto tutto sopra
--
Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi

andrestu Profilo | Expert

be non so a priori quanti record verranno eliminati/inseriti in quelle tabelle, sicuramente pochi, probabilmente conterranno al massimo una decina di record che non verranno mai modificati.
e per quanto riguarda la riduzione delle prestazioni nell'effettura l'inserimento calcolando prima il primo numero disponibile non è da considerarsi visto che sarà un operazione rara.

>Anche perchè, pensa a tutti quei record che si legano a quell'id (che potrebbero non avere Foreign Key) o quelli "storicizzati", che legame avrebbero? Un record aveva un id una volta, poi quell'id è stato usato da altri.. Se vuoi ricostruire una storia? Eviterei questo tipo di approccio.

Questa è una cosa non da poco a cui avevo pensato in effetti non vale la pena rischiare di creare disordine nei dati, anche se per il momento la storicizzazione non è considerata non si sa mai.
Conclusione: meglio cambiare tipo di approccio. o utilizzo uno smallint oppure lascio così utilizzando un identity...

Grazie del suggerimento


Andrea Restucci - Web Developer

alx_81 Profilo | Guru

A priori non escludo mai soluzioni, è solo che mi metto nell'ottica di pensare anche allo spreco di altri tipi di risorse (cpu, sviluppo, manutenzione, tempi).
Ci sarebbe da capire anche se ad esempio dovessi mostrare quegli id, senza spingerti nella storicizzazione..
Pensa alle stampe, scontrini, ecc.. Se tu indichi quegli id, è brutto collegarvi altre fonti.

>Conclusione: meglio cambiare tipo di approccio. o utilizzo uno
>smallint oppure lascio così utilizzando un identity...
Diciamo che nel tuo caso, se sai veramente tutto a priori, direi che puoi tenerti i tuoi tinyint e se proprio sfori, alter dei campi, credo sia la scelta migliore.

>Grazie del suggerimento
figurati, quando si possono valutare soluzioni è sempre un piacere.
Se ritieni che ti abbia aiutato, accetta la risposta così chiudiamo il thread
--
Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi

andrestu Profilo | Expert

>direi che puoi tenerti i tuoi tinyint e se proprio sfori, alter dei campi

con 'alter dei campi' intendi fare il cambio del tipo da tinyint a smallint con database a regime?
si che si passa da un tipo più piccolo ad uno più grande quindi non dovrebbero esserci problemi, ma farlo con Db pieno di record mi preoccupa un pò, secondo la tua esperienza quali potrebbero essere le conseguenze?
è un operazione che Sql riesce a gestire tranquillamente?
(e con questa chiudiamo giuro)

Andrea Restucci - Web Developer

alx_81 Profilo | Guru

>con 'alter dei campi' intendi fare il cambio del tipo da tinyint a smallint con database a regime?
alter del tipo del campo, sì

>si che si passa da un tipo più piccolo ad uno più grande quindi
>non dovrebbero esserci problemi, ma farlo con Db pieno di record
>mi preoccupa un pò, secondo la tua esperienza quali potrebbero
>essere le conseguenze?
>è un operazione che Sql riesce a gestire tranquillamente? (e con questa chiudiamo giuro)
nulla di che, basta non farlo durante il lavoro degli altri, prevedi uno script di notte ad esempio.

--
Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi

andrestu Profilo | Expert

ok grazie

Andrea Restucci - Web Developer
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2017
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5