È una cattiva pratica avere diverse relazioni uno-a-uno reciprocamente esclusive?


38

Dire, una tabella carha relazione uno-a-uno a tavoli electric_car, gas_care hybrid_car. Se a carè electric_car, non può più apparire in gas_caro a hybrid_car, ecc.

C'è qualcosa di sbagliato in tale design? Alcuni problemi che possono verificarsi lungo la strada?

Risposte:


59

I diversi tipi di auto sono un'istanza di un problema generale che emerge più e più volte nella modellazione dei dati. Si chiama "generalizzazione / specializzazione" nella modellazione ER e "superclasse / sottoclasse" nella modellazione di oggetti.

Un modellatore di oggetti utilizza le funzionalità di ereditarietà incorporate nel modello a oggetti per risolvere il problema abbastanza facilmente. Le sottoclassi estendono semplicemente la superclasse.

Il modellatore relazionale deve affrontare un problema. come progettare le tabelle in modo da emulare i benefici che si otterrebbero dall'eredità?

La tecnica più semplice si chiama ereditarietà a tabella singola . I dati su tutti i tipi di auto sono raggruppati in un'unica tabella per le auto. C'è una colonna, car_type, che raggruppa tutte le auto di un solo tipo. Nessuna auto può appartenere a più di un tipo. Se una colonna è irrilevante, per esempio, per le auto elettriche, verrà lasciata NULL nelle righe relative alle auto elettriche.

Questa semplice soluzione funziona bene per i casi più piccoli e più semplici. La presenza di molti NULL aggiunge un po 'al sovraccarico di archiviazione e un po' al recupero delle spese generali. Lo sviluppatore potrebbe dover apprendere la logica a tre valori di SQL se i test booleani vengono eseguiti su colonne nullable. All'inizio può essere sconcertante, ma ci si abitua.

Esiste un'altra tecnica, chiamata ereditarietà delle classi . In questo progetto, ci sono tabelle separate per gas_car, electric_car e hybrid_car, oltre a una tabella combinata, car, per tutti loro. Quando desideri tutti i dati su un tipo specifico di auto, ti unisci al tavolo dell'auto con l'apposito tavolo specializzato. Ci sono meno NULL in questo progetto, ma fai di più. Questa tecnica funziona meglio nei casi più grandi e complessi.

Esiste una terza tecnica chiamata chiave primaria condivisa. Questa tecnica viene spesso utilizzata in combinazione con l'ereditarietà della tabella delle classi. Le tabelle specializzate per le sottoclassi hanno, come chiave primaria, una copia della chiave primaria della voce corrispondente nella tabella dell'auto. Questa colonna ID può essere dichiarata come chiave primaria e chiave esterna.

Ciò comporta una piccola programmazione extra quando si devono aggiungere nuove auto, ma rende i giunti semplici, facili e veloci.

Superclass e sottoclassi accadono continuamente nel mondo reale. Non aver paura. Ma prova il tuo progetto iniziale per le prestazioni. Se il tuo primo tentativo è semplice e solido, sarai in grado di modificarlo per accelerarlo.


3
Wow grazie! Questo è perfetto per quello che stavo cercando di capire. L'ereditarietà delle tabelle di classe sembra essere esattamente ciò di cui ho bisogno. Ho cambiato la mia risposta accettata a questo per i futuri lettori poiché penso che copra completamente la domanda, non solo il mio caso.
Arthur Tarasov,

6
Ottima risposta qui. Un consiglio: documentare accuratamente queste decisioni di progettazione. Qualunque percorso segua, non sarà ovvio quando qualcuno sta esaminando la struttura del database. Alcuni database come Postgres ti consentono di associare un commento ai metadati di colonne, tabelle e simili.
Basil Bourque,

Non si affronta la restrizione a impedire che le auto elettriche siano anche auto ibride. Hai bisogno di una tabella separata per quello.
jmoreno,

2
Hai ragione. Se aggiungi un campo car_type alla tabella cars, puoi limitare le auto all'appartenenza a un solo tipo, a scapito della deviazione dalla piena normalizzazione. Un buon DBMS ti permetterà di definire un vincolo di controllo che impedirà a un'auto di entrare in più di una tabella specializzata. C'è un po 'di sovraccarico in questo, vai ad aggiungere nuove auto.
Walter Mitty,

@WalterMitty ma senza un car_typecampo, come faresti a sapere quale tabella cercare i dettagli durante il recupero dei dati? Devi leggere tutte e tre le tabelle per vedere quale ha i dati su quel carrecord specifico ?
Josh, parte

12

Non c'è nulla di sbagliato nell'avere tutti i sottotipi di entità nel modello necessari per riflettere la realtà dei dati che si sta tentando di modellare. La domanda non è se i sottotipi siano una cattiva pratica. Il problema potrebbe essere: è un buon modello ?

Ad esempio, sotto il tuo esempio, cosa fai con qualcosa come un'Audi A4 eTron, che è un ibrido plug-in? È una "macchina elettrica" ​​o una "macchina ibrida"?

L'altra domanda che ti devi porre è perché stai scrivendo dei sotto-caratteri? Quanti predicati distinti hai nei tuoi sottotipi? Qualcuno di questi predicati è condiviso tra i sottotipi? La situazione potrebbe complicarsi.

La digitazione secondaria non viene utilizzata nella progettazione del database per la classificazione. È possibile eseguire la classificazione con codici, chiavi esterne per tabelle di codici o con flag. La sottotipo viene utilizzata per modellare insiemi di predicati distinti per diversi tipi di cose di interesse. Se stai usando sottotipi solo per la classificazione, questa è una cattiva pratica.

Se i tuoi sottotipi modellano in modo chiaro e inequivocabile insiemi di predicati diversi per le cose che interessano al tuo database, allora è una buona pratica, indipendentemente da quanti sottotipi hai bisogno.


Grazie, temevo di prepararmi una specie di trappola. Il mio problema è che ognuno dei sottotipi avrà molte colonne. Alcuni si sovrapporranno e li inserirò in una cartabella, ma molti non lo faranno e verranno inseriti in una tabella dei sottotipi. Ad esempio, sarà qualcosa di simile alla memorizzazione di parti elementari di tipi di auto. Il motore di un'auto elettrica può avere circa 100 parti, un motore a benzina 75 parti e un ibrido 125 parti. 50 parti sarebbero comuni e conservati in cars, mentre il 50, 25 e 75 saranno in electric_car, gas_care hybrid_cartavoli
Arthur Tarasov
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.