Vincoli in un database relazionale - Perché non rimuoverli completamente?


20

C'è qualche motivo per costruire vincoli tra le tabelle (all'interno di SQLserver) al giorno d'oggi? In tal caso, quando? La maggior parte delle applicazioni nella mia area sono basate su principi di oggetti e le tabelle sono unite su richiesta. La domanda si basa sulla necessità dell'applicazione. Non caricherò un sacco di tabelle vincolate per una semplice ricerca, che a sua volta (dopo l'azione) richiedono una semplice ricerca reciproca.

Strumenti ORM come EntityContext, Linq2Data, NHibernate gestiscono anche i vincoli da soli, almeno sai quali tabelle hanno bisogno l'una dell'altra. Fare vincoli all'interno del server significa solo fare (forzare) le stesse modifiche due volte?

Di solito questa non è una domanda da prendere, ma questo database è progettato in modo abbastanza diverso. Il design sembra regolare, rispecchiando principalmente gli oggetti utilizzati dalle applicazioni. Ciò che mi disturba sono tutti i vincoli configurati all'interno di SQLserver con "non a cascata". Ciò significa che devi giocare a "cerca e trova" durante la codifica di nuove query di database. Alcuni casi richiedono fino a 10 livelli di un ordine esatto per effettuare una singola eliminazione.

Questo mi sorprende e non sono sicuro di come gestirlo.

Nel mio mondo semplice, questa impostazione fa perdere i vincoli alla maggior parte dello scopo. OK se si accede al database dagli host senza conoscere il progetto.

Come agiresti in questo scenario?
Perché non rimuovere tutti i vincoli da db e tenerli a livello di applicazione?


6
Avevi intenzione di accedere sempre ai dati tramite un singolo strumento ORM? O avevi intenzione di divertirti a replicare correttamente tutti i vincoli su ogni strumento ORM in uso?
Donal Fellows

1
Per il mio ultimo commento a Peter devo essere d'accordo. Il punto di affidare tutti i vincoli alla base di codice (e rimuoverli da db) era molto stretto e probabilmente sono pienamente applicabili ad applicazioni di breve durata. Probabilmente anche per alcuni sviluppatori / progetti RAD.
Indipendente,

4
Minore nitpick: penso che diventi un po 'confuso quando chiamate le connessioni di chiave esterna tra le tabelle "relazioni". Le "relazioni" in un database relazionale sono le tabelle stesse, non le connessioni. Soprattutto quando continuiamo a parlare di "design relazionale" - ciò significa tabelle o significa chiavi esterne?
Thomas Padron-McCarthy,

Grazie. Chiamo le "connessioni tra le tabelle" per i vincoli. Quindi, probabilmente hai ragione nel vedere "database relazionale" per i principi di progettazione delle tabelle (struttura delle tabelle). Una descrizione ancora più precisa sarebbe "modello di progettazione", quando riferito al database "relazione contro oggetto".
Indipendente

1
Il database sopravviverà al codice dell'applicazione. Inoltre, il tuo ORM sta danneggiando le prestazioni dell'applicazione e c'è una buona probabilità che finirai per volerlo bypassare almeno in alcuni casi d'uso. Se non lo conosci ora, lo saprai alla fine. samsaffron.com/archive/2011/03/30/… . Inoltre, la rimozione di tutti i vincoli rende il database completamente incapace di proteggere la propria integrità quando viene abusato da app diverse dalla tua, che potrebbe essere qualsiasi cosa, da un'altra app reale a un dirigente in corridoio con Excel.
Craig,

Risposte:


46

Due motivi generali per non rimuovere le controindicazioni dal DB :

  • È possibile accedervi da più app, ora o in futuro , che possono o meno utilizzare ORM. Anche se gli sviluppatori di queste app duplicano fedelmente tutti i vincoli lì (che possono essere significativamente più difficili utilizzando soluzioni non ORM di livello inferiore), è sempre un lavoro extra. E in caso contrario, anche una piccola omissione è sufficiente per interrompere l'integrità dello schema ... che è qualcosa che non vuoi rischiare. Nella maggior parte delle aziende, i dati memorizzati nel loro DB sono la linfa vitale della loro attività, quindi la sua integrità deve essere garantita con qualsiasi mezzo. E il mezzo più collaudato per raggiungere questo obiettivo è implementare il maggior numero possibile di vincoli nel DB.
  • Query Optimizer si basa molto sui vincoli noti a livello di DB. Se si rimuovono i vincoli, le prestazioni della query potrebbero iniziare a deteriorarsi . Potresti non notarlo immediatamente, ma un giorno ti colpirà e potrebbe essere troppo tardi per risolverlo facilmente. La natura delle cose è che le prestazioni del DB tendono a ridursi al momento del picco di carico, quando c'è la minima possibilità di apportare miglioramenti di progettazione attenti e ben ponderati, supportati da misurazioni esatte delle prestazioni e analisi dettagliate per individuare le cause alla radice.

Il tuo caso concreto sembra che lo schema DB potrebbe essere stato originariamente generato da uno strumento ORM (o progettato da qualcuno che non ha molta esperienza con il mondo relazionale), quindi non è ottimale dal punto di vista relazionale. Probabilmente è meglio analizzarlo e migliorarlo verso un design relazionale più "naturale", mantenendolo coerente con le viste ORM. Può essere utile coinvolgere un esperto di DB in questa analisi.


5
@Jonas, quindi parla con il ragazzo dei problemi percepiti con il suo design DB. Relazionali e orientati agli oggetti sono due mondi diversi: né un "miglioramento" rispetto all'altro di per sé, ed entrambi hanno il loro posto. Progettare un'app C # su principi relazionali è un errore tanto grave quanto progettare un DB in modo OO.
Péter Török,

3
@Jonas, riflettendo sui tuoi aggiornamenti: se hai bisogno di scrivere query troppo complesse per ottenere cose apparentemente semplici rispetto allo schema del DB, è o un segno che il design del DB è inadeguato per il suo scopo - o che non sei abbastanza esperto (per favore non offenderti, dal tuo post non è ovvio quanto tu abbia esperienza con SQL. Come disclaimer, io stesso sono ben lungi dall'essere un esperto.)
Péter Török

1
Probabilmente ho alcune espressioni da imparare, per rendermi percepibile :). Ho riletto la domanda e le risposte e devo invertire. Ci sono sicuramente un punto di forza avere DB come master per tutti i vincoli. Tutti i sistemi devono essere progettati da questo. Una visione molto ristretta per dire che la base di codice avrebbe funzionato. Se ogni sistema può avere la propria decisione sui vincoli, finirà in un alto chapparral con relazioni suggerite errate e interi tavoli orfani. Altrimenti, si verifica successivamente con altri programmatori.
Indipendente,

8
"È possibile accedervi da più app, ora o in futuro." Per non parlare dell'amministratore del database, che esegue query SQL non elaborate per risolvere un problema con il database, mentre gli utenti sono in attesa ...
Thomas Padron-McCarthy

5
+1: se db memorizza i dati aziendali (non solo la configurazione dell'app ecc.), Allora la probabilità che il database
rimanga

27

Le applicazioni possono andare e venire, ma i dati vivono per sempre. Nella mia azienda il DB ha più di 30-40 anni, sopravviverà finché esisterà la società. Le applicazioni cambiano, gli sviluppatori vanno e vengono. È meglio avere integrità e un buon modello di dati logici. In questo modo qualcuno può guardare i dati e ottenere una comprensione significativa senza dover passare attraverso una base di codice complessa. Questo aiuta anche a riferire in modo significativo. Inoltre, le applicazioni possono e avranno bug e il vincolo DB è una protezione da ciò. La mia posizione predefinita è quella di avere più vincoli (FK e check) possibili.
L'unico motivo per non avere un vincolo sarebbe se il modello di progettazione non lo consente, ad esempio Tabella per gerarchia o problemi di prestazioni.


Dirò, stai facendo un consiglio molto saggio qui. La mia opinione potrebbe corrispondere meglio allo sviluppo RAD o qualunque sviluppo in cui le applicazioni hanno una durata di vita breve - Solo per motivi di manutenzione ridotta durante lo sviluppo.
Indipendente

15

Ciò che mi disturba sono tutti i vincoli configurati all'interno di SQLserver con "non a cascata".

Questo non mi disturba, significa che qualcuno ha mostrato buon senso. Le eliminazioni a cascata spesso sono molto dannose per il database. Al primo posto, a volte si desidera che un'eliminazione fallisca se si hanno dati nelle tabelle correlate. Ad esempio, se hai un cliente che ha un ordine in passato, non vuoi che venga eliminato o perdi i dati su chi era l'ordine e una cancellazione a cascata eliminerà il record che rovinerebbe i tuoi rapporti finanziari .

Sembra che tu pensi che la facilità di sviluppo sia la cosa più importante. Nel mondo dei database questo non è semplicemente vero. L'integrità dei dati è la prima cosa più critica seguita da vicino dalle prestazioni e dalla sicurezza dei dati. Se ci vuole più tempo per scrivere le query, allora così sia.

In genere, il database viene utilizzato da molte applicazioni = uno o più siti Web o applicazioni desktop, un'applicazione di reportistica, servizi Web, finestra di query, processi ETL, ecc. Se non si impongono contraffazioni a livello di database, si perde prima l'integrità dei dati come una di quelle applicazioni potrebbe non seguire tutte le regole. In secondo luogo, è necessario codificare più volte tali contorni e riscriverli se si decide di utilizzare un'applicazione diversa in un secondo momento. In terzo luogo, non è possibile controllare in anticipo se sarà necessario eseguire una sorta di attività di manutenzione dei dati che non si verificherà attraverso l'applicazione (ad esempio, correggere i dati da un'importazione di dati di un cliente non valida o modificare tutti i 10.000.000 di record da un client a un altro cliente quando la società viene acquistata da un concorrente). In genere gli sviluppatori di applicazioni non fanno '


Grazie per la risposta. Tutti i processi e tutti i tipi di applicazione di cui parli, dovrebbero parlare con un DAL (che a sua volta conterrebbe i vincoli). MA! Il tuo punto è perfetto e il tuo commento è buono. Sidenote: Sì. Tendo a provare modi per facilitare lo sviluppo. Per me, meno complessità può sopportare meno modi di sbagliare. Questo non è "vuoi svilupparti più facilmente / più velocemente", anche se potrebbe essere - se è gestito male. Quindi perché sto postando questa domanda! Vorrei anche che qualcuno avesse un buon senso se questa non cascata fosse scelta con senso, non al 100% come in questo scenario. Devo scoprire ragioni.
Indipendente,

@Jonas, ci possono essere anche motivi di prestazioni. Dipende da un numero intero di record figlio. OK se stai eliminando piccoli gruppi ma se milioni di record potrebbero essere attivati, è meglio fare batch e non bloccare tutte le tabelle mentre si verifica l'intero processo. In generale molti dbas non consentiranno cancellazioni a cascata solo per quel motivo in quanto possono bloccare un sistema prod se un'eliminazione influisce su troppi record.
HLGEM,

2
No, tutti i processi non dovrebbero parlare con un DAL. I processi ETL in genere non fanno né cose che devono accadere a livello di database che incidono su molti record quando si verificano cambiamenti di grandi dimensioni (come il client che viene acquistato). Né puoi vietare a nessuno di utilizzare mai la finestra della query per apportare una modifica una tantum. Non ho mai visto un database che non ha imposto vincoli a livello di database che non ha avuto problemi di integrità nel tempo.
HLGEM,

10

Ho letto da qualche parte una volta che diceva sostanzialmente: i dati sono la chiave della tua applicazione . Se accedi MAI ai dati solo attraverso la tua interfaccia utente (e intendo sempre , come in questo momento e per sempre, per tutta l'eternità ... o per tutta la durata della tua applicazione), non hai bisogno di vincoli di database. Ma c'è sempre la possibilità che qualcosa di diverso dall'app stessa debba toccare i dati, ad esempio un servizio Web, un'API pubblica, un'attività di rake / lavoro SQL / cron / script automatico, quindi ti risparmierai un sacco di potenziali problemi nel strada mantenendo i vincoli del DB.

Credo fermamente che questo è l'unico settore dello sviluppo software in cui si dovrebbe non applicare DRY (e sto aspettandomi uno stuolo di downvotes per questa affermazione). I tuoi dati sono il cuore e l'anima della tua applicazione - se mai corrotti irreparabilmente, il gioco è finito. Vale la pena IMO per applicare i vincoli ovunque siano necessari. Se ciò significa sotto forma di trigger e vincoli a livello di DB, convalide sul lato server sul middleware e Javascript sul lato client sull'interfaccia utente (per le app Web), allora è IMO un male necessario per garantire che i dati siano sempre incontaminati .


6

Sai cosa significa ORM? Mappatura relazionale di oggetti. Citando Wikipedia "tecnica per convertire dati tra sistemi di tipo incompatibile ". Sì, i modelli relazionali e degli oggetti non si adattano insieme. Gli ORM eseguono una conversione abbastanza buona, rispettando le regole di entrambi i sistemi di tipo. Gli RDBMS sono organizzati in modo tale da ottenere l'integrità dei dati utilizzando i vincoli. In generale, l'integrità è una cosa molto bella da avere, quindi gli ORM tendono a usarli quando creano un modello di dati per archiviare i dati degli oggetti. Il tuo ORM probabilmente ha una buona ragione per usare vincoli "non a cascata". E se questo ti costringe a fare query complicate invece di creare / aggiornare / eliminare determinati oggetti, allora qualcosa non va nella tua configurazione ORM.

Se consideri fastidioso il concetto relazionale, perché non usi il database degli oggetti? Qualche tempo fa erano lenti (motivo per cui la maggior parte delle persone usa ancora RDBMS) ma da quello che ho sentito le cose sono cambiate un po '. Ti libereresti di tutti i pignoli relazionali. Semplicemente oggetti dentro, oggetti fuori.


L'argomento riguarda lo spostamento della funzionalità di vincolo dal DB e si basa su impostazioni / sviluppo all'interno della base di codice (ad es. Parlando in rete: Entity / Linq2Sql).
Indipendente,

Sì, lo so, ma il mio punto è che devi prima capire perché i vincoli ci sono in primo luogo e quindi perché potrebbe essere una cattiva idea eliminarli.
Jacek Prucia,

Mosso! Non lasciato cadere. Capisco che ti penti della conoscenza della domanda, di cui non si trattava.
Indipendente,

Non puoi davvero spostare nulla tra sistemi incompatibili. Stai per eliminare i vincoli DB, introdurre i vincoli dell'applicazione e sperare semplicemente che funzionino allo stesso modo (il che potrebbe rivelarsi vero e falso). Ad ogni modo la mia sincera scusa se ho frainteso la tua domanda.
Jacek Prucia,

Grazie! "Sposta" significa "mossa" letteraria. Ciò significa che si creano vincoli di applicazione (buona espressione) in ogni sistema. Almeno ogni sistema che non può condividere lo stesso DAL. Un esempio molto carino sono state le richieste dirette da un amministratore di database che "correggono qualcosa". Nessun vincolo di db e mancanza di conoscenza del design possono comportare dati orfani o dati completi, completamente derisi.
Indipendente,

6

Bene, questo è quello che ha fatto eBay e probabilmente hanno uno dei più grandi database al mondo:

http://www.dba-oracle.com/oracle_news/news_ebay_massive_oracle.htm http://www.addsimplicity.com/downloads/eBaySDForum2006-11-29.pdf

Nonostante ciò che è stato detto sopra sull'aumento delle prestazioni da parte dell'integrità referenziale, può effettivamente essere degradato; ecco perché enormi database hanno abbandonato i loro vincoli e fatto il lavoro a livello di applicazione. E per quanto ne so è l'unica vera buona ragione.

Eliminando questi vincoli, perdi essenzialmente la tua rete di sicurezza che mantiene i dati puliti e che causa i propri problemi. Così come per tutto è un atto di bilanciamento. Immagino che in generale mantenere l'integrità referenziale sia la cosa giusta da fare.

Avendo lavorato in un ambiente di sviluppo con una forte integrità referenziale, so che dal punto di vista dello sviluppatore può essere un dolore totale; spesso in un ambiente di sviluppo un po 'di dati sporchi non ha importanza e capire come eliminare una riga potrebbe richiedere un'ora o più. Tuttavia, può anche essere molto utile, poiché i vincoli rendono esplicito lo schema.


Finalmente qualcuno che mi capisce :-). Hai perfettamente ragione, l'equilibrio è un punto davvero grande qui. Spostare i vincoli a livello di applicazione può essere un'alternativa sicura, se fatto come punto strategico. Sarebbe bello con alcuni URL di siti dimostrati prestazioni degradate a causa di forti vincoli / integrità.
Indipendente,

10
Sì e non dimenticare - non dimenticare - che Ebay, come Facebook e Amazon, è un gazillion volte più grande del 99,99% dei database, e ciò che è buono per loro è probabilmente molto diverso da ciò che è buono per il tuo database.
Tony Andrews,

2
E eBay, Facebook, Amazon probabilmente non usano database senza vincoli per il loro software finanziario e contabile o il loro software di inventario o i loro dati sulle risorse umane o ovunque dove non è fondamentale perdere i dati.
HLGEM,

2
Se hai abbastanza tempo, competenza e denaro, puoi eventualmente programmare qualsiasi RDBMS, web server o sistema operativo per soddisfare un'esigenza specifica.
JeffO,

1
eBay non lo ha fatto fino a quando l'enorme volume di dati che stavano affrontando ha sostanzialmente superato la capacità dei server di database di far fronte, e hanno avuto i milioni da investire nella loro nuova architettura. Se stai facendo miliardi di transazioni al giorno, allora risolvi la questione sulla rimozione dei vincoli e vai su un sistema totalmente basato su code, senza transazioni e scalabile in modo massiccio come eBay. Altrimenti, non sottovalutare il server di database e non lasciare il database soggetto a corruzione dei dati rimuovendo tutti i vincoli.
Craig,

4

Primo: la mia risposta: No, non dovresti fare affidamento solo sull'applicazione per occuparti dei tuoi dati.

Ciò indica un dibattito più ampio: gli ORM hanno incoraggiato una cultura di disprezzo per l'interazione "diretta" tra DB, spesso a spese della normalizzazione / integrità referenziale. Le tabelle sono forzatamente mappate su gerarchie di oggetti arbitrarie, a scapito della progettazione implicita nel modello relazionale. Il disaccoppiamento favorito da OOP è probabilmente sacrificato qui poiché l'applicazione fa sentire il suo design nella struttura dei dati. Mentre ORM ha dimostrato una grande utilità, sembra essere basato sull'abuso o la diffidenza di SQL.

Nuovi paradigmi stanno (ri) emergendo, ad esempio la programmazione funzionale. Se il team di sviluppo decide di adottare una nuova metodologia di programmazione, quali implicazioni avrà per i dati che sono stati strutturati in base ai requisiti dell'ORM?

Sono d'accordo con @Jacek Prucia - Penso che ORM sia una cattiva corrispondenza per RDBMS, opterei personalmente per un DBAL su RDBMS o scegliere un OODB con ORM.


+1 per parlare di alternative all'argomento. L'altra parte del dibattito è ovviamente: "Quanto sarebbero dannosi alcuni dati?" e la risposta può essere la cancellazione o il miliardo di inserimenti di denaro sul conto bancario di un milione di dollari. Oltre ad alcuni dati orfani che vengono rimossi con buone routine di pulizia. Il riassunto di questo argomento, sembra coerenza con il costo della flessibilità. Che a sua volta dipende completamente dalla gravità del contenuto e dell'uso del db.
Indipendente,

3

I vincoli sono la tua unica garanzia di coerenza e integrità dei dati a livello di database. Certo, puoi applicare i vincoli utilizzando il codice dell'applicazione, ma cosa succede se, in futuro, devi modificare direttamente i dati? Potresti capire come mantenere l'integrità dei dati, ma qualcun altro potrebbe non farlo. Mantenere i vincoli a livello di dati garantisce che l'integrità sia garantita anche quando qualcuno è in cerca di scimmie in luoghi che non capiscono.

Inoltre, supponiamo che l'applicazione debba essere riscritta, ma con lo stesso database in atto. Tutti quei vincoli nel codice chiedono solo bug che impediscono l'ingresso di alcuni dati consentendo al contempo dati errati.

Durante lo sviluppo, mantenerlo semplice. I vincoli ti consentono di farlo. (Detto questo, quando un vincolo genera un errore, non restituire lo stesso errore all'utente. Rendere comprensibile l'errore.)

(Per quanto riguarda il problema della cascata: questa è una buona cosa. Preferirei gettare un errore che alcuni altri record debbano essere eliminati prima, piuttosto che fare affidamento sulla cascata per ottenere tutto a posto. Le cascate sono belle in teoria, ma non necessariamente così in pratica.)


2

Un problema con vincoli in un database è che forniscono al programma informazioni limitate su ciò che è fallito e su come risolverlo. Ciò significa che, per una gestione agevole, è spesso necessario ripetere il controllo dei vincoli nell'applicazione, e quindi il controllo dei vincoli del database è uno sforzo sprecato.

Ciò comporta il rischio di compromettere l'integrità dei dati, quindi abbiamo degli svantaggi qui. Per i dati importanti, garantire l'integrità dei dati è quasi sempre più importante delle prestazioni ed è molto meglio fallire una transazione anche se sembra arbitraria piuttosto che incasinare i dati.

Per rimuovere in sicurezza i vincoli, è quindi fondamentale proteggere l'accesso al database in modo che nulla possa modificare il database senza verificarne i vincoli. Ciò non è affidabile quando si scrivono nuove applicazioni o si escogitano modi ad hoc per gestire i dati, poiché tutto ciò che serve è un errore e il database è corrotto.

Pertanto, per eliminare i vincoli del database, è necessario stabilire cosa può e cosa non si può fare con il database in anticipo, in modo che tutte le applicazioni possano essere scritte, riviste e testate ampiamente. Tutti i requisiti del database devono essere stabiliti in anticipo e qualsiasi modifica ai requisiti del database richiederà un ampio lavoro. Questa è una sorta di metodologia a cascata congelata, che funziona solo in casi molto specifici. (Progettare, attuare e soddisfare i requisiti è molto simile a camminare sull'acqua. Qualcosa deve essere prima congelato e se non è abbastanza congelato i risultati possono essere disastrosi.)

Un caso in cui funziona sono le enormi applicazioni aziendali come PeopleSoft e SAP, in cui l'applicazione fa già praticamente tutto e ci sono modi accuratamente definiti per estenderla. Vi sono altre possibilità, molto rare.

Quindi, a meno che tu non lavori su un progetto aziendale molto grande (e non vorrei farlo) o non riesci a camminare sull'acqua liquida, lascia quei vincoli nel database.


1
Grazie per la risposta. I vincoli saranno nel db per questo progetto! Sono completamente convinto :). Avrò anche più occhi quando deciderò su progetti futuri e in discussioni con altre parti.
Indipendente,

1
Considera anche che senza i vincoli, lo stai lasciando al codice dell'applicazione stesso per rilevare che ha rovinato. Questo è lo stesso codice dell'applicazione che ha violato il vincolo nel tuo esempio, tra l'altro, il vincolo che ha salvato il tuo database dall'incoerenza o dalla corruzione dei dati. L'utilizzo dei vincoli non significa automaticamente anche prestazioni inferiori, tra l'altro, e il mancato utilizzo dei vincoli lascia il database esposto in modo che non possa proteggersi.
Craig,
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.