All'interno di un'applicazione Web su cui sto lavorando, tutte le operazioni del database sono astratte utilizzando alcuni repository generici definiti su Entity Framework ORM.
Tuttavia, per avere un design semplice per i repository generici, tutte le tabelle coinvolte devono definire un numero intero univoco ( Int32
in C #, int
in SQL). Fino ad ora, questo è sempre stato il PK del tavolo e anche il IDENTITY
.
Le chiavi esterne sono molto utilizzate e fanno riferimento a queste colonne intere. Sono richiesti sia per coerenza che per la generazione di proprietà di navigazione da parte dell'ORM.
Il livello applicazione esegue in genere le seguenti operazioni:
- caricamento iniziale dei dati dalla tabella (*) -
SELECT * FROM table
- Aggiornamento -
UPDATE table SET Col1 = Val1 WHERE Id = IdVal
- Elimina -
DELETE FROM table WHERE Id = IdVal
- Inserisci -
INSERT INTO table (cols) VALUES (...)
Operazioni meno frequenti:
- Inserimento di massa -
BULK INSERT ... into table
seguito (*) da tutto il caricamento dei dati (per recuperare identificatori generati) - Eliminazione di massa : si tratta di una normale operazione di eliminazione, ma "voluminosa" dal punto di vista di ORM:
DELETE FROM table where OtherThanIdCol = SomeValue
- Aggiornamento in blocco - questa è una normale operazione di aggiornamento, ma "ingombrante" dal punto di vista di ORM:
UPDATE table SET SomeCol = SomeVal WHERE OtherThanIdCol = OtherValue
* tutte le tabelle di piccole dimensioni vengono memorizzate nella cache a livello di applicazione e quasi tutte SELECTs
non raggiungono il database. Un modello tipico è carico iniziale e un sacco di INSERT
s, UPDATE
s e DELETE
s.
Sulla base dell'utilizzo corrente dell'applicazione, ci sono poche possibilità di raggiungere mai 100 milioni di record in una qualsiasi delle tabelle.
Domanda: Dal punto di vista di un DBA, ci sono problemi significativi che posso incontrare avendo questo limite di progettazione della tabella?
[MODIFICARE]
Dopo aver letto le risposte (grazie per l'ottimo feedback) e gli articoli di riferimento, mi sento come se dovessi aggiungere ulteriori dettagli:
Specifiche attuali dell'applicazione - Non ho parlato dell'attuale applicazione Web, perché voglio capire se il modello può essere riutilizzato anche per altre applicazioni. Tuttavia, il mio caso particolare è un'applicazione che estrae molti metadati da un DWH. I dati di origine sono piuttosto disordinati (denormalizzati in modo strano, con alcune incongruenze, nessun identificatore naturale in molti casi ecc.) E la mia app sta generando entità separate e chiare. Inoltre,
IDENTITY
vengono visualizzati molti degli identificativi generati ( ), in modo che l'utente possa utilizzarli come chiavi aziendali. Questo, oltre a un massiccio refactoring del codice, esclude l'uso di GUID ."non dovrebbero essere l'unico modo per identificare in modo univoco una riga" (Aaron Bertrand ♦) - questo è un ottimo consiglio. Tutte le mie tabelle definiscono anche un VINCOLO UNICO per garantire che i duplicati aziendali non siano consentiti.
Progettazione basata su app front-end e progettazione basata su database : la scelta del design è causata da questi fattori
Limitazioni di Entity Framework : sono consentiti più PK di colonne, ma i loro valori non possono essere aggiornati
Limitazioni personalizzate : disporre di un'unica chiave intera semplifica notevolmente le strutture di dati e il codice non SQL. Ad esempio: tutti gli elenchi di valori hanno una chiave intera e valori visualizzati. Ancora più importante, garantisce che qualsiasi tabella contrassegnata per la memorizzazione nella cache possa essere inserita in una
Unique int key -> value
mappa.
Query di selezione complesse : questo non accadrà quasi mai perché tutti i dati di tabelle di piccole dimensioni (<20-30K record) vengono memorizzati nella cache a livello dell'applicazione. Questo rende la vita un po 'più difficile quando si scrive il codice dell'applicazione (più difficile scrivere LINQ), ma il database è molto più bello:
Visualizzazioni elenco : non genererà
SELECT
query al caricamento (tutto viene memorizzato nella cache) o query simili a questa:SELECT allcolumns FROM BigTable WHERE filter1 IN (val1, val2) AND filter2 IN (val11, val12)
Tutti gli altri valori richiesti vengono recuperati tramite ricerche nella cache (O (1)), quindi non verranno generate query complesse.
Modifica visualizzazioni : genererà
SELECT
istruzioni come questa:SELECT allcolumns FROM BigTable WHERE PKId = value1
(tutti i filtri e i valori sono int
s)