Che cosa è successo ai vincoli del database?


46

Quando rivedo i modelli di database per RDBMS, di solito sono sorpreso di trovare piccoli o nessun vincolo (a parte PK / FK). Ad esempio, la percentuale viene spesso memorizzata in una colonna di tipo int(mentre tinyintsarebbe più appropriato) e non vi è alcun CHECKvincolo per limitare il valore all'intervallo 0..100. Analogamente su SE.SE, le risposte che suggeriscono che i vincoli di controllo ricevono spesso commenti che suggeriscono che il database è il posto sbagliato per i vincoli.

Quando chiedo della decisione di non implementare i vincoli, i membri del team rispondono:

  • Né che nemmeno sanno che tali funzionalità esistono nel loro database preferito. È comprensibile dai programmatori che utilizzano solo ORM, ma molto meno dai DBA che dichiarano di avere più di 5 anni di esperienza con un determinato RDBMS.

  • O che impongono tali vincoli a livello di applicazione e duplicare tali regole nel database non è una buona idea, violando SSOT.

Più recentemente, vedo sempre più progetti in cui non vengono utilizzate nemmeno le chiavi esterne. Allo stesso modo, ho visto alcuni commenti qui su SE.SE che mostrano che agli utenti non interessa molto l'integrità referenziale, lasciando che l'applicazione li gestisca.

Quando chiedono ai team la scelta di non usare gli FK, dicono che:

  • È PITA, ad esempio quando si deve rimuovere un elemento a cui si fa riferimento in altre tabelle.

  • NoSQL oscilla e non ci sono chiavi esterne lì. Pertanto, non ne abbiamo bisogno in RDBMS.

  • Non è un grosso problema in termini di prestazioni (il contesto è in genere applicazioni Web Intranet di piccole dimensioni che lavorano su set di dati di piccole dimensioni, quindi, anche gli indici non contano troppo; a nessuno importa se le prestazioni di una determinata query passano da 1,5 s . a 20 ms.)

Quando guardo l'applicazione stessa, noto sistematicamente due schemi:

  • L'applicazione disinfetta correttamente i dati e li controlla prima di inviarli al database. Ad esempio, non è possibile archiviare un valore 102come percentuale nell'applicazione.

  • L'applicazione presuppone che tutti i dati che provengono dal database siano perfettamente validi. Cioè, se 102arriva in percentuale, o qualcosa, un posto andrà in crash o verrà semplicemente visualizzato come è per l'utente, portando a situazioni strane.

  • Mentre oltre il 99% delle query viene eseguito da una singola applicazione, nel tempo iniziano a comparire gli script, sia script eseguiti manualmente quando necessario, sia cron job. Alcune operazioni sui dati vengono eseguite anche manualmente sul database stesso. Sia gli script che le query SQL manuali hanno un rischio elevato di introdurre valori non validi.

Ed ecco che arriva la mia domanda:

Quali sono i motivi per modellare i database relazionali senza vincoli di controllo e infine anche senza chiavi esterne?


Per quel che vale, questa domanda e le risposte che ho ricevuto (in particolare l'interessante discussione con Thomas Kilian) mi hanno portato a scrivere un articolo con le mie conclusioni sull'argomento dei vincoli del database .


8
Sento per te, ma sembra che tu sappia già perché i vincoli sono una buona idea, quindi non c'è molto da aggiungere sotto forma di risposta. Noterò tuttavia che la mancanza di vincoli non è un fenomeno nuovo, l'ho visto per decenni in database progettati da sviluppatori senza una forte comprensione dei database relazionali. Penso che raramente sia una decisione di progettazione deliberata.
Jacques B

1
@JacquesB: puoi pubblicare una risposta, dal momento che "L'ho visto per decenni" dà una visione molto diversa da quella che ho avuto di un fenomeno che è apparso tre-quattro anni fa (dato che ho lavorato in IT per meno di un decennio, la mia visione del fenomeno è probabilmente sbagliata). Pertanto, anche le conclusioni sarebbero molto diverse.
Arseni Mourzenko,

1
Lavoriamo con molti clienti. E mentre distribuire una nuova versione del nostro software è un gioco da ragazzi, aggiornare tutti i databasechema ovunque è una seccatura. Ecco perché abbiamo molti vincoli nel software. Oh sì, una piccola percentuale per una percentuale spesso non è una buona idea perché le percentuali possono essere frazioni.
Pieter B,

1
Votando per riaprire questa domanda poiché è stata erroneamente chiusa come "principalmente basata sull'opinione" quando le risposte finora dimostrano che non è così.
David Arno,

3
Sono con te al 110%.
Periata Breatta,

Risposte:


28

È importante distinguere tra diversi casi d'uso per i database.

Il tradizionale database aziendale è accessibile da più applicazioni e servizi indipendenti e forse direttamente da utenti autorizzati. È fondamentale disporre di uno schema e vincoli ben ponderati a livello di database, quindi un bug o una svista in una singola applicazione non corrompono il database. Il database è critico per l'azienda, il che significa che dati incoerenti o corrotti possono avere risultati disastrosi per l'azienda. I dati vivranno per sempre mentre le applicazioni vanno e vengono. Questi sono i luoghi che possono avere un DBA dedicato per garantire la coerenza e l'integrità del database.

Ma ci sono anche sistemi in cui il database è strettamente integrato con una singola applicazione. Applicazioni stand-alone o applicazioni Web con un singolo database incorporato. Fintanto che il database è accessibile esclusivamente da una singola applicazione, è possibile considerare i vincoli ridondanti, purché l'applicazione funzioni correttamente. Questi sistemi sono spesso sviluppati da programmatori con un focus sul codice dell'applicazione e forse non una profonda comprensione del modello relazionale. Se l'applicazione utilizza un ORM, i vincoli potrebbero essere dichiarati a livello di ORM in una forma più familiare ai programmatori dell'applicazione. Nella fascia bassa abbiamo applicazioni PHP che utilizzano MySQL e per molto tempo MySQL non ha supportato affatto i vincoli di base, quindi è stato necessario fare affidamento sul livello dell'applicazione per garantire coerenza.

Quando gli sviluppatori di questi diversi background si incontrano si ottiene uno scontro culturale.

In questo mix otteniamo la nuova ondata di database distribuiti "cloud storage". È molto difficile mantenere coerente un database distribuito senza perdere il vantaggio in termini di prestazioni, quindi questi database spesso evitano i controlli di coerenza a livello di database e sostanzialmente consentono ai programmatori di gestirlo a livello di applicazione. Le diverse applicazioni hanno requisiti di coerenza diversi e, sebbene il motore di ricerca di Google abbia la priorità sulla disponibilità rispetto alla coerenza tra i loro server, sono disposto a scommettere che il loro sistema di gestione stipendi viene eseguito su un database relazionale con molti vincoli.


5
+! 1 per menzionare l'elefante nella stanza: il falso presupposto che un'applicazione usi solo un DB e che un DB sia usato da una sola app
Tulains Córdova,

4
@ TulainsCórdova, pensavo che l'elefante nella stanza fosse il sistema di gestione stipendi di Google. :)
Machado,

5
@Machado Questo è geniale: "Sono disposto a scommettere che il loro sistema di gestione stipendi viene eseguito su un database relazionale con molti vincoli".
Tulains Córdova,

2
È inoltre utile disporre di database correttamente vincolati poiché il codice dell'applicazione non è ACID.
Matthew Whited,

3
Solo per enfatizzare il commento di @MatthewWhited, non è possibile per le applicazioni applicare alcuni tipi di vincoli inter-riga / inter-tabella senza eseguire il blocco e l'esecuzione di query extra. Un RDBMS può farlo a costi molto più bassi.
David Aldridge il

15

Oggigiorno sempre più sistemi sono in esecuzione in ambienti distribuiti, sul cloud e adottano la tecnica per "ridimensionare", anziché "ridimensionare". Questo è ancora più importante se hai a che fare con applicazioni online di Internet, come le app di e-commerce.

Detto questo, tutte le applicazioni che dovrebbero ridimensionare sono vincolate dal Teorema CAP , in cui devi scegliere 2 di 3: Coerenza, Disponibilità e Tolleranza alle partizioni (tolleranza agli errori di rete).

Studiando il teorema della PAC noterai che non c'è molta scelta, ma scegliere di perdere la disponibilità o la coerenza, dal momento che non puoi MAI fidarti della rete il 100% delle volte.

In generale, diverse applicazioni possono permettersi di essere incoerenti per un periodo di tempo ragionevole, ma non possono permettersi di non essere disponibili per gli utenti. Ad esempio, una sequenza temporale leggermente non ordinata in Facebook o Twitter è meglio che non avere affatto accesso a una sequenza temporale.

Pertanto, diverse applicazioni scelgono di eliminare i vincoli del database relazionale, poiché i database relazionali sono davvero bravi a coerenza, ma a costo della disponibilità.

Nota personale: anch'io sono vecchio stile e ho lavorato con alcuni sistemi finanziari molto vecchi in cui la coerenza dei dati è un requisito di prim'ordine per la maggior parte del tempo e sono un grande fan dei vincoli del database. I vincoli del database sono l'ultima linea di difesa contro anni e anni di cattivo sviluppo e team di sviluppatori che vanno e vengono.

"Est modus in rebus". Continuiamo a utilizzare la coerenza "basso livello" del DB in cui la coerenza è un requisito di prima classe. Ma a volte, lasciarlo andare non è un grosso peccato dopo tutto.

-- MODIFICARE: --

Dato che c'è una piccola modifica nella domanda, c'è un altro motivo legittimo per eliminare i vincoli nel database, IMO. Se si progetta un prodotto da zero, dove si progetta il proprio sistema per supportare la tecnologia multi-database, è possibile accontentarsi del minimo comune denominatore tra i database supportati e infine eliminare qualsiasi vincolo, lasciando tutta la logica di controllo per la tua applicazione.

Sebbene sia legittimo, è anche un'area grigia per me, perché oggi non riesco a trovare alcun motore di database che non supporti semplici vincoli come quello proposto nella domanda originale.


"Oggi non riesco a trovare alcun motore di database che non supporti semplici vincoli come quello proposto nella domanda originale." MySQL supporta ancora i vincoli CHECK?
Vincent Savard,

@VincentSavard, forse non è esattamente CHECK MS SQL, ma una sorta di restrizione lo fa: dev.mysql.com/doc/refman/5.7/en/constraint-invalid-data.html
Machado,

@Machado - non si tratta di vincoli specifici, tuttavia, tanto quanto identificare quando le query includono dati che non possono essere rappresentati nei tipi appropriati. Il che rappresenta un netto miglioramento della situazione anni fa, quando MySQL semplicemente ignorava silenziosamente tali valori.
Periata Breatta,

1
@PeriataBreatta, da un lato, non ho mai capito fino in fondo perché MySQL fosse il database OSS "di fatto" scelto dagli sviluppatori di siti Web, quando PostgreSQL era completamente disponibile ed era più avanzato. Forse è stato più facile da installare, non lo so.
Machado,

@machado - Non posso esserne certo , ma so che all'inizio (a metà degli anni '90) tendevo a preferire mysql a postgres (che non è stato ribattezzato postgresql fino a dopo) a causa di un malinteso che postgres non supportava SQL (le sue prime versioni no - aveva il suo linguaggio di query chiamato "postquel" - e non mi ero tenuto aggiornato con il suo sviluppo, quindi non mi ero reso conto che avevano aggiunto il supporto SQL a circa nello stesso momento in cui mysql è diventato disponibile). Se questo malinteso era comune, è possibile che mysql sia andato avanti proprio per questo. E una volta che era avanti, gli effetti di rete hanno preso il sopravvento.
Periata Breatta,

10

Quali sono i motivi per modellare i database relazionali senza vincoli di controllo e infine anche senza chiavi esterne?

Per prima cosa chiariamo che sto parlando solo di RDBM, non di database no-SQL.

Ho visto alcuni database senza FK o PK, per non parlare dei vincoli, ma ad essere sinceri sono una minoranza. Forse perché lavoro in una grande azienda.

Nella mia esperienza nel corso degli anni posso dire che alcuni motivi possono essere:

  • Nel caso di principianti o programmatori amatoriali , conoscete le capacità di modellismo
  • Uso estensivo o quasi esclusivo degli ORM senza alcun contatto reale con il mondo dei database
  • Assenza di un DBA o di altri esperti di modellizzazione dei dati in una squadra o in un piccolo progetto
  • Mancanza di coinvolgimento del DBA o esperto di modellizzazione dei dati nelle prime fasi dello sviluppo
  • Decisioni di progettazione deliberate da una parte della comunità di sviluppatori che considera che anche un vincolo di controllo che impone che una certa colonna può avere solo 1,2 or 3come un valore, o che la colonna "età" deve essere >= 0è "avere la logica di business nel database" . Anche alcune clausole predefinite sono considerate da alcuni come una logica aziendale che non appartiene a un database, come puoi vedere in molte domande e risposte recenti in questo stesso sito. Gli sviluppatori che lo considerano, ovviamente, utilizzerebbero il minor numero possibile di vincoli e farebbero tutto nel codice, anche l'integrità e / o l'unicità di riferimento. Penso che questa sia una posizione estrema.
  • Uso di RDBM come archivi di valori-chiave , sia per emulare il comportamento no-SQL sia perché i requisiti erano abbastanza semplici da essere soddisfatti usando le tabelle RDBMS come repository di valori-chiave isolati.
  • Supponendo che il database verrà sempre scritto da "l'app" e che nessuno avrà mai bisogno di eseguire un massiccio caricamento di dati, o modificare o inserire righe tramite un client SQL (in molti casi per correggere i dati errati nell'app inserita). Nel migliore dei casi, ci sarà sempre un'altra app (oltre a "l'app") che invierà istruzioni DML al database: un client SQL.
  • Non rendersi conto che i dati appartengono al proprietario dell'attività , non all'app.

Detto questo, vorrei affermare che gli RDBMS sono software molto avanzati che sono stati costruiti sulle spalle dei giganti e si sono dimostrati molto efficienti per molti requisiti aziendali, liberando i programmatori di banali compiti di far rispettare l'integrità referenziale su una serie di file binari o file di testo. Come dico sempre "non viviamo più in un mondo con un'unica app-one-database" . Per lo meno un client SQL emetterà DML oltre a "l'app". Quindi il database dovrebbe difendersi da errori umani o di programmazione in misura ragionevole

In quei ben noti tipi di requisiti in cui RDBMS non si ridimensiona bene, abbracciano senza dubbio la tecnologia no-SQL . Ma è preoccupante la proliferazione di database relazionali senza vincoli in cui migliaia di righe di codice (generate o dattiloscritte) dedicate a far rispettare ciò che RDBMS dovrebbe far valere in modo più efficiente.


3

Esistono vincoli esterni che guidano le decisioni tecnologiche. Ci sono solo alcune situazioni in cui hai la necessità e il lusso di utilizzare i vincoli dei campi del database su base regolare.

  1. Le aziende hanno sviluppatori sia per app che per database insieme a DBA, ma la maggior parte degli sviluppatori non funziona in questo tipo di ambiente. Fanno il più possibile nel codice. Inoltre, alcuni dal lato del database non vengono coinvolti nelle regole aziendali. Principalmente sono lì per far funzionare le cose. Non spingeranno mai per vincoli nel db. Dover gestire app legacy, integrazioni, migrazioni, fusioni, acquisizioni e un vincolo db può essere la soluzione migliore.
  2. Il sovraccarico del db può creare un collo di bottiglia che non si risolve facilmente lanciando più macchine al problema. Ci sono alcune situazioni in cui il linguaggio db non gestisce alcuni problemi di programmazione senza un grave calo delle prestazioni, quindi non puoi pianificare l'utilizzo di un vincolo per tutto. Stackoverflow ha un server di database perché lanciare 2 a un problema è una sfida.
  3. Test automatizzati: ci stanno arrivando ma molti sviluppatori di database sono in ritardo alla festa insieme ai framework IDE / testing.
  4. Distribuzione: più roba db la rende più complicata. Cosa succede quando un aggiornamento al database di un client non è consentito perché ci sono dati che violano il vincolo? Game over a meno che tu non abbia un modo per affrontarlo. Nella tua app, puoi decidere di consentire all'utente di gestirlo in base alle esigenze o di incaricare alcuni amministratori di farlo in un batch.
  5. Solo l'app / api / service scriverà mai i dati nel database, quindi perché preoccuparsi? Questo regge il più delle volte ed è per questo che non è comune.
  6. Gestire gli errori db è abbastanza difficile senza che centinaia di violazioni dei vincoli possano contrastare se tutto esce dal colpo. La maggior parte è felice di stabilire una connessione e ottenere il nome della tabella corretto.

Molti team di sviluppo non vogliono dare troppo controllo a uno sviluppatore di database. Sei fortunato se ne ottieni più di uno, quindi le vacanze sono molto divertenti. Non molti richiedono il controllo assoluto sul dominio del database e si assumono la responsabilità di ogni query, regola aziendale, prestazioni, disponibilità, sicurezza e quali dati vanno a quale RAID. Ecco le procedure memorizzate che è consentito eseguire. Divertiti. Non pensare nemmeno a toccare un tavolo.


2

Questo è un problema che ho lottato con tutta la mia carriera (quasi 40 anni) e anche quando ho scritto il mio DBMS. Una descrizione del mio end point è qui: http://unibase.zenucom.com . Quindi ecco i miei pensieri.

  1. In generale, la maggior parte dei vincoli viene gestita meglio nell'applicazione in modo che parti diverse dell'applicazione possano imporre vincoli diversi. ad esempio un codice di stato potrebbe non essere applicabile in tutte le giurisdizioni.
  2. A parte attenzione del%. I markup sono> 100% o sei al verde :)
  3. I vincoli sono meglio descritti negativamente. cioè ciò che non possono essere, non ciò che dovrebbero essere. È sempre un elenco più semplice.
  4. Le chiavi esterne sono sempre valide e devono essere utilizzate. Punto. FK è uno dei pochi costrutti semantici in un RDBMS e molto utile. La difficoltà maggiore sta nel decidere se lasciare un valore penzolare se l'FK viene rimosso o utilizzare le righe dipendenti come motivo per non eliminare il record FK.
  5. I vincoli nel mondo reale sono generalmente più complessi di una restrizione del valore di un singolo campo.
  6. Alcuni vincoli, anche a livello di applicazione, si oppongono a buone operazioni. ad es. il controllo aggressivo della data nasconde errori in date apparentemente buone. È necessario un errore dell'operatore per ottenere una misura degli errori in date altrimenti sensibili.

1

I vincoli del database potrebbero essere stati un'idea intelligente, ma per quanto riguarda un uso pratico per loro? Prendi il tuo vincolo percentuale. Se lo applichi, il tuo DB rifiuterà felicemente percentuali non valide. E poi? Sarà necessaria la logica aziendale per gestire l'eccezione. Il che significa in realtà che la logica aziendale che scrive una percentuale errata ha già fallito altrove. Quindi in breve: l'unico vincolo pratico rimasto sono quelli che vedi (come PK / FK).


15
Non sono educatamente d'accordo con questo. Se hai davvero bisogno di coerenza dei dati, i vincoli del DB sono indispensabili, specialmente se la tua logica aziendale non riesce. In questo modo stai descrivendo lo scenario in cui si verificherebbe un fallimento silenzioso, in cui il danno causato da un errore percentuale errato verrebbe propagato ulteriormente nel sistema. Se si dispone di un vincolo DB a tale proposito, si fallirebbe rapidamente e quindi si darebbe agli sviluppatori di business logic la possibilità di vedere presto l'errore e patchare il sistema di business logic, invece di consentire il danneggiamento dei dati al suo interno.
Machado,

5
La mia comprensione è che se viene violato il vincolo percentuale, non è necessario gestire questa eccezione, poiché tale violazione indica che esiste innanzitutto un bug nel codice (qualcuno utilizzava un intero semplice anziché un'istanza di Percentageclasse, o c'è un errore nella validazione stessa), al contrario di un caso eccezionale (come una connessione di rete è inattiva). Per me, la violazione dovrebbe portare a HTTP 500 per un'app Web o un arresto anomalo per un'app desktop, quindi dovrebbe essere registrato e corretto.
Arseni Mourzenko,

7
@ThomasKilian: no; esattamente il contrario. I dati errati non entreranno, in particolare perché ci sono vincoli del database. Se la tua logica aziendale è nel codice, non violerai mai quei vincoli in primo luogo. Se si è verificato un errore nel codice, tali vincoli ti avviseranno di questo errore, mantenendo il database al sicuro dagli scarti.
Arseni Mourzenko,

9
@ThomasKilian: Non penso che qualcuno stia litigando contro "farlo bene in primo luogo" - è probabilmente più che chiunque abbia un po 'di esperienza sappia che è una cattiva idea progettare un sistema partendo dal presupposto che lo farai ottenere tutto a posto la prima volta e non si verificheranno mai bug o errori durante la vita del sistema. I vincoli del DB assicurano che un errore o un errore non danneggi il database.
Jacques

3
@JacquesB Sto combattendo contro i mulini a vento. Se si inserisce la logica aziendale nel DB, può anche fallire come in primo luogo e non salvarti allo stesso modo. Ma (!) Ora hai una logica aziendale a cui non appartiene. Credere che il DB possa salvare la tua logica aziendale marcio è semplicemente sbagliato. La logica nel DB deve seguire le stesse regole dell'intera logica aziendale.
qwerty_so,

1

Più spesso in questi giorni, le persone utilizzano software (ad esempio Entity Framework) per generare automaticamente tabelle e colonne. L'idea è che non hanno bisogno di abilità SQL, liberando la capacità del cervello.

Le aspettative che il software "risolva le cose" sono spesso irrealistiche e non creano i vincoli che un umano vorrebbe.

Per risultati ottimali, creare tabelle utilizzando SQL e aggiungere manualmente i vincoli, ma a volte le persone non possono farlo.


Alcuni framework supportano l'aggiunta automatica di PK e FK (semi), ovviamente.
David Aldridge il
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.