PK autogenerate... amici o nemici? |
Home Page | Commenti | Articoli | Faq | Documenti | Ricerca | Archivio | Storie dalla Sala Macchine | Contribuire | Imposta lingua:en it | Login/Register
Ci tengo a precisare che quello che segue e' la MIA personale opinione, maturata dopo 15 anni passati a sviluppare, mantenere, debuggare e lavorare su un vario numero di sistemi basati su vari databases. Se non siete d'accordo con me, per cortesia mandatemi una mail con le vostre opinioni ed io le aggiungero' in coda in modo da avere una esposizione completa dei pro e dei contro. NOTA: non e' detto a priori che pubblichi la vostra mail, lo faro' solo se reputero' le vostre argomentazioni sufficientemente logiche e non gia' trattate in questo documento. Premetto che non penso che gli ID autogenerati siano negativi in senso assoluto. In alcuni casi non c'e' proprio nessuna altra scelta. Quello che non mi trova d'accordo e' il loro uso sempre e comunque, anche quando una scelta alternativa e' disponibile. Nel 98% dei casi che mi sono ritrovato davanti in cui una tabella aveva un'ID autogenerato vi erano un numero sufficiente di campi univoci da produrre un'ottima chiave non-autogenerata per la tabella stessa. Questo ha molto a che fare con una pessima (o nessuna) progettazione del database. In molti casi vedo tabelle con 10 campi di cui 9 accettano NULL e l'unico campo non-null e' l'ID. Se un campo puo' essere nullo le possibilita' che sia sempre nullo sono altissime. In tal caso e' meglio eliminare del tutto il campo. In teoria ogni campo di una tabella dovrebbe essere riempito con un valore valido (aka: non desumibile dal valore di altri campi) prima della de-normalizzazione. Se l'unico campo valido in una tabella e' l'ID, la possibilita' di ritrovarsi con 'n' record identici (salvo l'ID) aumenta. E tali record sono assolutamente inutili, un utente non e' in grado di distinguerli (e come potrebbe?), ne' di gestirli, l'intera struttura dati inizia a perdere di validita' e tutte le informazioni diventano sospette o inutili. Immaginiamo un sistema di fatturazione in cui (causa un baco di progettazione e/o di implementazione) lo stesso "cliente" e' stato inserito 10 volte. Abbiamo 10 fatture, quale e' il fatturato totale del cliente? Ma e' sempre lo stesso cliente o sono 10 clienti diversi che "sembrano" lo stesso? Il cliente telefona e chiede informazioni riguardo una fattura... troveremo la fattura o finiremo per dirgli che "tale fattura non esiste?" Che succede se arriva un controllo della finanza? Alcuni database consentono la generazione del valore indipendentemente dall'inserimento o meno del record, altri invece collegano la generazione con l'inserimento, in questo secondo caso il reperire il valore e' piuttosto complesso e dipende dalle capacita' del RDBMS e del sistema che si sta' usando per inserire i dati. Se la PK e' data dai valori del record, la avete prima ancora dell'insert in ogni caso. Riprendendo l'esempio di prima del sistema di fatturazione, per ricercare un cliente non si puo' utilizzare l'ID perche' tale ID non ha senso e l'utente non lo conosce, dovra' pertanto usare o una ricerca alfabetica o altro sistema, rallentando la ricerca e rischiando di ricevere piu' dati di quello che si cerca (un solo cliente). L'utente potrebbe anche non essere in grado di distinguere il cliente "giusto" una volta trovato nel sistema in mezzo agli altri "simili". Supponendo invece che l'ID sia composto da informazioni che l'utente conosce, e' possibile sveltire le ricerche e le possibilita' di reperire piu' record si riducono. L'utente e' in grado di distinguere i singoli record perche' conosce le informazioni (le ha inserite lui). Avendo lavorato presso una grossa societa' di distribuzione, posso dire con certezza che forzare gli utenti ad inventarsi un sistema di classificazione da' i suoi frutti. Dopo una settimana tutti erano in grado di recitare senza errori meta' dei codici senza doverli nemmeno ricercare. I codici errati venivano individuati senza sforzo e le ricerche (nonostante la non eccelsa velocita' dell'hardware) erano rapide e ritornavano sempre il risultato voluto. E non e' che il database fosse piccolo (175.000 articoli). Viceversa, in una seconda societa' e con un sistema molto piu' piccolo, la presenza di ID autogenerati ha portato rapidamente ad una esplosione di record 'n'-uplicati. Dopo meno di 6 mesi l'anagrafica clienti contava 273.000 record (e rotti), mentre i clienti "effettivi" erano meno di 20.000. Qui' il problema non era solo la pessima progettazione del sistema, ma anche la pessima realizzazione che impediva delle ricerche valide, per cui l'utente finiva con il re-inserire il cliente in quanto non riusciva piu' a ritrovarlo. In alcuni casi l'unico modo di avere una PK per una tabella e' mettere tutti i campi in sequenza. A questo punto conviene (se il database lo consente) passare ad una Index Organized Table, ovviamente pagandone lo scotto... La mia opinione comunque e' che la PK in molti casi se la deve gestire il computer, quindi quanto essa sia lunga non e' che faccia una grande differenza. Vero, ma in molti casi lo scopo di una ricerca parziale e' "perche' non mi ricordo esattamente...". Lo scopo di una PK mnemonica e' evitare le ricerche parziali il piu' possibile.
Vero anche questo. Se la PK di una tabella e' composta da 7 campi, gli stessi devono essere nelle tabelle collegate per poter referenziare la precedente. Questo e' uno degli argomenti piu' a favore di ID autogenerati (un solo campo da riportare). Il pro in questo caso e' che nel 90% dei casi una interrogazione sulla tabella "figlia" non deve necessariamente fare una Join sulla tabella "madre" per recuperare quei 7 campi, e se quei 7 campi sono gli unici che interessano, non serve fare una Join ma basta una query su una tabella singola. Questo non ha senso. La teoria dice che non si possono modificare le PK. Se avete progettato un sistema che vi consente di cambiare le PK vi conviene assicurarvi di riportare i cambiamenti sulle tabelle collegate o cambiare mestiere.
Dove lavoro usano delle chiavi che definiscono "parlanti".
Per fare un esempio il codice cliente e' un char(9) nella forma: 200xxyyyy
dove le y sono autogenerate (valori fra '0000' e '9999') e i valori xx
assumono i valori '02' per clienti italiani e '03' per clienti esteri.
Problema: aggiungiamo una nuova categoria e la chiamiamo '05'(???)
Lo abbiamo fatto ma abbiamo dovuto controllare tutti i report sui clienti
(per non parlare di un altro paio di cosette). Poi ogni tanto inseriscono un
cliente nella categoria '05' mentre in realta' non lo era.
Cosi' se il cliente e' appena stato inserito lo cancelliamo noi (gli utenti
non possono cancellare nulla) altrimenti viene fuori un casino: chi ha fatto
il DB ha pensato bene di non usare PK e FK quindi di modificare il valore di
una PK non se ne parla neppure...
PS: non ho mai capito a cosa serve il prefisso '200'...
Da quello che dici mi pare evidente che il problema qui' non sono i codici in se', ma il modo come il sistema e' stato progettato. Le chiavi "parlanti" non mi sembrano molto "parlanti". Ovviamente, una cattiva progettazione del sistema non puo' essere risolta da una PK autogenerata o meno. |
I commenti sono aggiunti quando e soprattutto se ho il tempo di guardarli e dopo aver eliminato le cagate, spam, tentativi di phishing et similia. Quindi non trattenete il respiro.
gufo_rosso Di gufo_rosso postato il 11/04/2008 08:17
Dissento. Il linguaggio di programmazione o il programma se ne fregano di quanto sono lunghe le chiavi, se parliamo di programmatore pigro e' un altro discorso
Non permettono la modifica (ovvero NON vanno modificati) se cancelli il record.
Le chiavi primarie non vanno mai modificate a prescindere da come sono fatte. Se hai un sistema che lo consente il sistema e' bacato.
le relazioni a me sembrano piu facili
a te. a me no
il contro se devi recuprare una relazioni devi fare join (o theta)
anche solo per un valore, se parlimo di clienti il campo univoco e' PIVA o CF
il CF non e', non e' mai stato e mai sara' un valore univoco
in caso di un magazzino hai il codice (che puo essere inventato da user, o autogenerato).
un contro e' la dimensione degli indici su numero di record alto
E chi se ne... della dimensione degli indici? Quello fa parte delle specifiche del software, inoltre, con i dischi fissi attuali, hai voglia a fare indici...
Luca Di Luca postato il 16/08/2008 08:39
Perche' non lo e', visto che puo' essere "calcolato" al momento. Il fatto che contenga il nome, cognome data e luogo di nascita della persona, non ne fa un buon candidato. In una citta' di una certa dimensione, ci sono troppe possibilita' che due persone con nome sufficientemente simile siano nate nello stesso giorno. Ceeeerto, puoi chiedere al ministero e yada yada yada... ma guardiamo in faccia la realta': chi lo fa?
Lex Di Lex postato il 24/08/2008 13:30
P.S.
Naturalmente la progettazione è stata fatta con gli ID autogenerati (almeno così ho sentito)
Paolo Brigati Di Paolo Brigati postato il 08/09/2008 12:26
il fatto che il CF possa essere auto-calcolato e che le uniche informazioni che contiene siano il nome, cognome, data e luogo di nascita ne fanno, per definizione, un codice NON-univoco. Puo' darsi che, se tu informi l'ufficio competente, quelli possano cambiarlo, ma per informare l'ufficio, devi sapere che il codice e' non-univoco. Se il codice fosse progettato per essere univico, non potresti autocalcolarlo. Quindi assumere che tale codice sia univoco e' sempre e comunque un errore
Davide Di Davide postato il 12/09/2008 08:30
In merito a chiavi composte da più campi, devo però aggiungere che lavorando con strumenti tipo Object/Relational mapping, la cruda realtà è che se vuoi tenerti le chiavi naturali (o business key, che fà più figo) devi faticare molto di più e alcune funzionalità ti sono precluse se non hai oggetti con un solo campo come chiave.
Questa cosa mi fa pensare che chi scrive questi ORM è bravissimo nella programmazione ma ha un'idea di database un po' particolare.
il che mi fa pensare che usare tali strumenti dovrebbe venire per secondo, e come prima cosa dovrebbe esserci usare la propria testa.
Davide Di Davide postato il 12/09/2008 10:27
Antonio Di Antonio postato il 23/09/2008 14:09
Gabriele Paggi Di Gabriele Paggi postato il 09/10/2008 11:25
@ Gabriele Paggi Di Diegoepoimaria postato il 24/09/2012 12:16
Mio padre spesso racconta che, da giovane neolaureato, lavorò per qualche anno in una ditta chiamata Sogei, come programmatore, e li conobbe l'ideatore del codice fiscale, e spesso ne elogia i meriti e ne racconta le vicissitudini.
Il codice fiscale è univoco poichè è emesso , come hanno già detto, solo e soltanto dall'Agenzia delle Entrate.
Il motivo per cui fu scelto è che si voleva un codice che avesse una qualche attinenza con la realtà, e che potesse ricordare il nome della perosna interessata ... grave errore ...
Se si fosse scelto un codice NON ricostruibile, nessuno avrebbe pensato di crearselo da solo in caso di smarrimento del tesserino, e ne tantomeno ci sarebbero siti che "tentano" di calcolarlo, con metodi che possono anche ssere giusti, am che mancano dell'unico e fondamentale controllo: l' unicità.
In teoria è quindi giusto usare il codice fiscale, ma, in pratica, dal momento che esso viene inserito da utonti senza la minima cognizione di causa ( e senza la possibiltià alcuna di controllo sulla esattezza del codice, dato che l'Agenzia delle Entrate può modificare, cioè "sbagliare" ad hoc il codice ), concordo sul fatto che non sia giusto usarlo come chiave primaria.
Per inciso: Ora capisco tutta la rottura di scatole di codice che il mio capo schiavista mi stà facendo scrivere per la gestione del DB ...
-- Diegoepoimaria
crwn Di crwn postato il 22/12/2008 14:08
Di Anonymous coward postato il 29/01/2011 23:21
Se alla chiave primaria autogenerata si aggiunge una chiave univoca gestita dagli utonti (per capirci: quella che essi vedono ed usano per identificare l'elemento della tabella) si hanno a mio modo di vedere notevoli vantaggi, per esempio quello di poter adottare un criterio di codifica della chiave unica e poi avere un ripensamento senza per questo dover metter mano alla rifasatura delle dipendenze. Un esempio per chiarire: nel db ho i prodotti e le righe delle spedizioni dei medesimi; se la riga della spedizione fa riferimento al prodotto attraverso la chiave autogenerata, posso cambiare a piacimento il codice esterno (la chiave univoca) del prodotto senza perdere la relazione con le spedizioni avvenute.
@ Anonymous coward Di Davide Bianchi postato il 30/01/2011 09:57
posso cambiare a piacimento il codice esterno
Questo puzza di cattiva progettazione/analisi lontano un kilometro. Perche' dovresti voler cambiare il codice esterno?
Di Massimo M. postato il 24/09/2012 21:33
Io nei miei db ho sempre usato una pk autoincrementante, usando poi, se necessario, le chiavi composte dai campi.
Per un semplice motivo: ho una tabella padre e una figlia, perche' nei programmi dovrei scrivere "select from figlia where campo1=pippo and campo2=pluto and campo3=paperino and....."
quando posso scrivere
select from figlia where idpadre=2?
una semplice pk autogenerata mi porta via pochissimo spazio, non e' pesante, non mi limita nell'avere chiavi composte da campi, e mi permette di accorciare le select e di non dovermi ricordare "la pk del padre e' codicearticolo+taglia+colore o codicearticolo+taglia+colore+ordine o ...."
per quanto riguarda il "una pk non puo' essere mai cambiata", beh, si quella e' la teoria, in pratica ho assistito a parecchi cambi di pk, del tipo da "codice+taglia" a "codice+taglia+colore". Vero, e' stato mal progettato dall'inizio, cio' non toglie che succeda.
-- Massimo M.
@ Massimo M. Di Davide Bianchi postato il 25/09/2012 14:52
perche' nei programmi dovrei scrivere
Per lo stesso motivo per cui si usano variabili dal nome diverso da 'a' e 'b' e 'c'. Perche' IL CODICE DIVENTA PIU' LEGGIBILE e FACILMENTE MANTENIBILE! Perche' poi quando vai a rivedere la struttura capisci al volo cosa lega tabbela 'a' alla tabella 'b' (ed a tutte le altre).
-- Davide Bianchi
Di lufo88 postato il 15/05/2013 20:06
Parlando di MySQL mi hanno spiegato che c'è un motivo per usare gli id autoincrementali (e usare UNIQUE su altri campi). A quanto pare essendo MySQL quello che è (una mezza fetecchia) Se gli aggiungi record con un ID autoincrementale come PK non deve rigenerare d'accapo l'indice sulla PK (cosa non vera con PK più "sensate").
-- lufo88
Di Rigongia postato il 08/03/2014 22:18
Solo una annotazione sul presunto contro del "se cambio la PK si scassa tutto" : anche su quella mezza fetecchia di MySQL esiste (quindi do per scontato che esista anche su sistemi un pelo piu' tosti) la possibilita' quando si definisce una chiave esterna di specificare cosa fare in caso di update o delete dei campi a cui quella chiave si riferisce. Ergo se cambio il valore della PK si smazza in automatico il DBMS ...
-- Rigongia
Davide Bianchi, lavora come Unix/Linux System Administrator presso una societa' di Hosting in Olanda.
Il presente sito e' frutto del sudore della mia fronte (e delle mie dita), se siete interessati a ripubblicare uno degli articoli, documenti o qualunque altra cosa presente in questo sito per cortesia datemene comunicazione (o all'autore dell'articolo se non sono io), cosi' il giorno che faccio delle aggiunte potro' avvisarvi e magari mandarvi il testo aggiornato.
Questo sito era composto con VIM, ora e' composto con VIM ed il famosissimo CMS FdT.
Questo sito non e' ottimizzato per la visione con nessun browser particolare, ne' richiede l'uso di font particolari o risoluzioni speciali. Siete liberi di vederlo come vi pare e piace, o come disse qualcuno: "Finalmente uno dei POCHI siti che ancora funzionano con IE5 dentro Windows 3.1".