Che cosa è successo ai vincoli del database?

45

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

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

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

  • O che applicano tali vincoli a livello di applicazione e la duplicazione di quelle regole nel database non è una buona idea, violando SSOT.

Più di recente, 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 mostra che agli utenti non interessa molto l'integrità referenziale, lasciando che sia l'applicazione a gestirlo.

Quando chiedi ai team la scelta di non usare 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 sono necessari in RDBMS.

  • Non è un grosso problema in termini di prestazioni (il contesto è di solito piccole applicazioni web intranet che lavorano su piccoli set di dati, quindi in effetti anche gli indici non contano troppo: a nessuno interesserebbe una performance di un data la query passa da 1,5 s a 20 ms.)

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

  • L'applicazione disinfetta correttamente i dati e li controlla prima di inviarli al database. Ad esempio, non c'è modo di memorizzare un valore 102 come percentuale attraverso l'applicazione.

  • L'applicazione presuppone che tutti i dati provenienti dal database siano perfettamente validi. Cioè, se 102 è in percentuale, o qualcosa, da qualche parte 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, gli script iniziano a comparire, ovvero gli script eseguiti a mano quando necessario o i lavori cron. Alcune operazioni sui dati vengono anche eseguite manualmente sul database stesso. Entrambi gli script e le query SQL manuali presentano un rischio elevato di introduzione di valori non validi.

E qui arriva la mia domanda:

Quali sono i motivi per modellare i database relazionali senza controllare i vincoli e alla fine anche senza chiavi esterne?

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

    
posta Arseni Mourzenko 29.11.2016 - 12:34
fonte

7 risposte

27

È 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 avere uno schema e dei vincoli ben ponderati a livello di database, quindi un bug o una svista in una singola applicazione non danneggia il database. Il database è business-critical, 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 la salute del database.

Ma ci sono anche sistemi in cui il database è strettamente integrato con una singola applicazione. Applicazioni stand-alone o applicazione Web con un singolo database incorporato. Finché il database è accessibile esclusivamente da una singola applicazione, è possibile considerare ridondanti i vincoli, a condizione che 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 un formato più familiare ai programmatori di applicazioni. Nella parte bassa abbiamo applicazioni PHP che usano MySQL, e per molto tempo MySQL non supportava affatto i vincoli di base, quindi aveva per fare affidamento sul livello dell'applicazione per garantire la coerenza.

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

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

    
risposta data 30.11.2016 - 08:54
fonte
15

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

Detto questo, tutte le applicazioni che dovrebbero essere ridimensionate sono vincolate dal CAP Teorema , dove è necessario scegliere 2 di 3: Coerenza, disponibilità e tolleranza della partizione (tolleranza di errore di rete).

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

In generale, diverse applicazioni possono permettersi di essere inconsistenti per un ragionevole lasso di tempo, ma non possono permettersi di non essere disponibili per gli utenti. Ad esempio, una timeline leggermente non ordinata su Facebook o Twitter è meglio che non avere accesso a una timeline.

Pertanto, molte applicazioni scelgono di lasciar andare i vincoli del database relazionale, dal momento che i database relazionali sono veramente buoni in Consistency, ma al 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 prima classe 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.

"Mod. est in rebus". Continuiamo ad usare la coerenza "di basso livello" di DB, dove la coerenza è un requisito di prima classe. Ma a volte, lasciarlo andare non è un peccato dopo tutto.

- MODIFICA: -

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, in cui si progetta il sistema per supportare la tecnologia multi-database, è possibile accontentarsi del minimo comune denominatore tra i database supportati e infine eliminare l'uso di eventuali vincoli, lasciando tutta la logica di controllo per la tua applicazione.

Anche se è legittimo, è anche un'area grigia per me, perché proprio non riesco a trovare alcun motore di database oggi che non supporta i vincoli semplici come quello proposto nella domanda originale.

    
risposta data 29.11.2016 - 13:13
fonte
10

What are the reasons to model relational databases without check constraints and eventually even without foreign keys?

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

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

Nella mia esperienza nel corso degli anni posso dire che alcune ragioni potrebbero essere:

  • Nel caso dei programmatori principianti o hobby , un ack di abilità di modellizzazione
  • Uso estensivo o quasi esclusivo di ORM senza alcun vero contatto con il mondo del database
  • Assenza di un esperto di DBA o di altri modelli di dati in un team o in un piccolo progetto
  • Mancanza di coinvolgimento dell'esperto di DBA o di modellazione dei dati nelle prime fasi dello sviluppo
  • Decisioni progettuali deliberate di una parte della comunità di sviluppatori che considera anche un vincolo di controllo che impone che una determinata colonna possa avere solo 1,2 or 3 come valore o che la colonna "età" deve essere >= 0 è "con business logic nel database" . Anche le clausole predefinite sono considerate da alcuni come una logica aziendale che non appartiene a un database, come potete vedere in molte domande e risposte recenti in questo stesso sito. Gli sviluppatori che considerano, ovviamente, utilizzerebbero il minor numero possibile di vincoli e faranno tutto nel codice, persino nell'integrità referenziale e / o nell'unicità. Penso che questa sia una posizione estrema.
  • Uso degli RDBM come memorie di valori-chiave , per emulare il comportamento non-SQL di perché i requisiti sono sufficientemente semplici da essere soddisfatti utilizzando le tabelle RDBMS come se fossero isolati repository di valori-chiave.
  • Supponendo che il database sarà sempre scritto da "l'app" e che nessuno avrà mai bisogno di fare un enorme carico di dati, o modificare o inserire righe tramite un client SQL (in molti casi correggere male dati inseriti nell'app). Nel migliore dei casi escenario ci sarà sempre un'altra app (oltre "l'app") che invia istruzioni DML al database: un client SQL.
  • Non capendo che i dati appartengono al proprietario dell'attività commerciale , non all'app.

Detto questo, vorrei precisare che RDBMS è un software molto avanzato che è stato costruito sulle spalle dei giganti e si è dimostrato molto efficiente per molti requisiti aziendali, liberando i programmatori di compiti banali di imporre l'integrità referenziale su una serie di file binari o di testo. Come dico sempre "non viviamo più in un mondo one-app-one-database" . Per lo meno un client SQL rilascerà DML oltre a "l'app". Quindi il database dovrebbe difendersi dagli errori umani o di programmazione in misura ragionevole

In quei ben noti tipi di requisiti in cui RDBMS non si adatta bene, abbraccia in ogni caso la tecnologia no-SQL . Ma preoccupa la proliferazione di database relazionali senza vincoli in cui migliaia di righe di codice (generate o tipizzate) sono dedicate a far rispettare ciò che l'RDBMS dovrebbe imporre per te in modi più efficienti.

    
risposta data 30.11.2016 - 12:48
fonte
3

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

  1. Le aziende hanno sviluppatori per entrambe le app e il database insieme a DBA, ma la maggior parte degli sviluppatori non funziona in questo tipo di ambiente. Fanno tutto il possibile in codice. Inoltre, alcuni sul lato del database non vengono coinvolti nelle regole aziendali. Sono principalmente lì per far funzionare le cose. Non spingeranno mai per i vincoli nel db. Avere a che fare con applicazioni legacy, integrazioni, migrazioni, fusioni, acquisizioni un vincolo db potrebbe essere la soluzione migliore.
  2. Il sovraccarico del db può creare un collo di bottiglia che non è facilmente risolvibile lanciando più macchine al problema. Ci sono alcune situazioni in cui il linguaggio db non gestisce alcuni problemi di programmazione senza un notevole impatto sulle prestazioni, quindi non è possibile pianificare l'utilizzo di un vincolo per tutto. StackOverflow ha un server di database perché lanciare 2 a un problema è una sfida.
  3. Test automatici: ci stanno arrivando ma molti sviluppatori di database sono in ritardo per la festa insieme all'IDE / testing framework.
  4. Distribuzione: più roba db lo rende più complicato. Cosa succede quando un aggiornamento al database di un cliente non è permesso perché ci sono dati che violano il vincolo? Game over a meno che tu non abbia un modo per affrontare questo. Nella tua app, puoi decidere di consentire all'utente di gestirlo come necessario o di istruire alcuni amministratori a farlo in un batch.
  5. Solo l'app / api / service scriverà mai dati nel database, quindi perché preoccuparsi? Questo è il più delle volte, motivo per cui non è comune.
  6. Gestire gli errori di db è già abbastanza difficile senza che centinaia di violazioni dei vincoli vengano prese in considerazione se tutto si risolve. La maggior parte è felice di stabilire una connessione e di ottenere il nome corretto della tabella.

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

    
risposta data 30.11.2016 - 22:57
fonte
2

Questo è un problema che ho faticato con tutta la mia carriera (quasi 40 anni) e anche quando scrivevo il mio DBMS. Una descrizione del mio endpoint è qui: link . Quindi ecco i miei pensieri.

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

I vincoli del database potrebbero essere stati un'idea intelligente, ma che ne è stata di un uso pratico per loro? Prendi il tuo limite di percentuale. Se lo applichi, il tuo DB rifiuterà felicemente le percentuali non valide. E poi? Avrai bisogno della 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 nel corto: l'unico vincolo pratico rimasto sono quelli che vedi (come PK / FK).

    
risposta data 29.11.2016 - 13:32
fonte
1

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

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

Per ottenere i migliori risultati, crea tabelle usando SQL e aggiungi manualmente i vincoli, ma a volte le persone non possono farlo.

    
risposta data 30.11.2016 - 13:13
fonte