La normalizzazione delle tabelle operative come suggerito da Transact Charlie, è una buona idea e salverà molti mal di testa e problemi nel tempo - ma ci sono cose come tabelle di interfaccia , che supportano l'integrazione con sistemi esterni e tabelle di report , che supportano cose come analitiche in lavorazione; e questi tipi di tabelle non dovrebbero necessariamente essere normalizzati - in effetti, molto spesso è molto, molto più conveniente e performante per loro non essere .
In questo caso, penso che la proposta di Transact Charlie per i tuoi tavoli operativi sia valida.
Ma aggiungerei un indice (non necessariamente univoco) a CompetitorName nella tabella Competitors per supportare join efficienti su CompetitorName ai fini dell'integrazione (caricamento di dati da fonti esterne) e aggiungerei una tabella di interfaccia nel mix: CompetitionResults.
I risultati della competizione devono contenere tutti i dati contenuti nei risultati della competizione. Lo scopo di una tabella di interfaccia come questa è rendere il più semplice e veloce possibile troncare e ricaricare da un foglio Excel o un file CSV, o qualunque sia il modulo in cui si trovano quei dati.
Tale tabella di interfaccia non dovrebbe essere considerata parte dell'insieme normalizzato di tabelle operative.Quindi puoi unirti a CompetitionResults come suggerito da Richard, per inserire record in concorrenti che non esistono già e aggiornare quelli che lo fanno (ad esempio se in realtà hai più informazioni sui concorrenti, come il loro numero di telefono o indirizzo e-mail).
Una cosa che vorrei notare - in realtà, il nome del concorrente, mi sembra, è molto improbabile che sia unico nei tuoi dati . In 200.000 concorrenti, potresti benissimo avere 2 o più David Smith, per esempio. Quindi ti consiglio di raccogliere maggiori informazioni dai concorrenti, come il loro numero di telefono o un indirizzo e-mail o qualcosa che è più probabile che sia univoco.
La tua tabella operativa, concorrenti, dovrebbe avere solo una colonna per ogni elemento di dati che contribuisce a una chiave naturale composita; ad esempio dovrebbe avere una colonna per un indirizzo email principale. Ma la tabella di interfaccia dovrebbe avere uno slot per vecchi e nuovi valori per un indirizzo di posta elettronica primario, in modo che il vecchio valore possa essere utilizzato per cercare il record in Concorrenti e aggiornare quella parte di esso con il nuovo valore.
Quindi CompetitionResults dovrebbe avere alcuni campi "vecchi" e "nuovi" - oldEmail, newEmail, oldPhone, newPhone, ecc. In questo modo puoi formare una chiave composita, in Concorrenti, da Nome concorrente, Email e Telefono.
Quindi, quando si ottengono alcuni risultati della competizione, è possibile troncare e ricaricare la tabella dei risultati della concorrenza dal foglio Excel o qualsiasi altra cosa, ed eseguire un singolo inserto efficiente per inserire tutti i nuovi concorrenti nella tabella dei concorrenti e un singolo aggiornamento efficiente da aggiornare tutte le informazioni sui concorrenti esistenti dai risultati della competizione. E puoi fare un singolo inserto per inserire nuove righe nella tabella CompetitionCompetitors. Queste cose possono essere fatte in una procedura memorizzata ProcessCompetitionResults, che può essere eseguita dopo aver caricato la tabella CompetitionResults.
Questa è una sorta di rudimentale descrizione di ciò che ho visto fare più volte nel mondo reale con Oracle Applications, SAP, PeopleSoft e un elenco di altre suite di software aziendali.
Un ultimo commento che farei è quello che ho già fatto in precedenza su SO: Se crei una chiave esterna che assicuri che un concorrente esista nella tabella dei concorrenti prima di poter aggiungere una riga con quel concorrente in esso ai concorrenti, assicurati che la chiave esterna è impostata per gli aggiornamenti e le eliminazioni in cascata . In questo modo, se è necessario eliminare un concorrente, è possibile farlo e tutte le righe associate a quel concorrente verranno eliminate automaticamente. Altrimenti, per impostazione predefinita, la chiave esterna richiederà di eliminare tutte le righe correlate da Competitori concorrenti prima di consentire l'eliminazione di un concorrente.
(Alcune persone pensano che le chiavi esterne non a cascata siano una buona precauzione di sicurezza, ma la mia esperienza è che sono solo un tremendo dolore nel sedere che sono più spesso che non semplicemente un risultato di una svista e creano un sacco di lavoro per i DBA. Avere a che fare con la gente che elimina accidentalmente cose è il motivo per cui si hanno dialoghi come "sei sicuro" e vari tipi di backup regolari e origini dati ridondanti. È molto, molto più comune voler effettivamente eliminare un concorrente, i cui dati sono tutti incasinato, ad esempio, che è quello di cancellarne accidentalmente uno e poi andare "Oh no! Non intendevo farlo! E ora non ho i risultati della competizione! Aaaahh!" Quest'ultimo è certamente abbastanza comune, quindi , devi essere preparato per questo, ma il primo è molto più comune,quindi il modo più semplice e migliore per prepararsi al primo, imo, è semplicemente fare aggiornamenti ed eliminazioni a cascata delle chiavi esterne.)
NVARCHAR(64)
colonna la tua chiave primaria (e quindi: il clustering) !! Prima di tutto - è una chiave molto ampia - fino a 128 byte; e in secondo luogo ha dimensioni variabili - di nuovo: non ottimale ... Questa è la scelta peggiore che puoi avere - le tue prestazioni saranno infernali e la frammentazione di tabelle e indici sarà sempre al 99,9% .....