Ich arbeite an einem Multiple-Choice-Online-Test-Projekt hier habe ich Datenbank entwickelt, um Ergebnis zu speichern, aber auf der Suche nach mehr optimierten Weg.
Anforderungen:
Mein Entwurf:
Tabellen:
Studenten
Stud_ID, Name, E-Mail
Tests
test_id, Testname, Dauer
Fragen
que_id, Frage, opt1, opt2, opt3, opt4, Antwort, test_id
Antworten
stud_id, que_id, antworte
Auf diese Weise können Antworten gespeichert werden, aber sie erhöhen die Anzahl der Datensätze, da für jede vom Schüler gelöste Frage ein neuer Datensatz in der Antworttabelle hinzugefügt wird.
z.B. Ein Test besteht aus 100 Fragen und 1000 Studenten machen diesen Test, für jeden Studenten gibt es 100 Datensätze für jede Frage und für 1000 Studenten 100k Datensätze.
Gibt es einen besseren Weg dies zu tun, wenn die Anzahl der Datensätze geringer ist.
Sie haben gute Arbeit geleistet. Soweit die Daten betroffen sind, ist das Design korrekt, aber unvollständig. Es gibt zwei Fehler:
opt1…opt4
ist eine sich wiederholende Gruppe, die 2NF bricht. Es muss in einer separaten Tabelle platziert werden.
Außerdem scheint es keinen Optionsnamen oder -deskriptor zu geben, der seltsam ist (was malt man auf der Seite neben jedem Optionsfeld?)
Wenn Sie jemals eine fünfte Option hinzufügen, ist das nun möglich; Wenn Sie Fragen mit weniger als vier Optionen haben, ist dies jetzt möglich.
Umgekehrt haben Sie eine feste Anzahl von Spalten, und wenn solche Änderungen in der Zukunft auftreten, müssen Sie sowohl die Datenbank als auch den vorhandenen Code ändern. Und der Code wird horrend sein (zusätzliche Verarbeitung statt direkter SELECTs)
Ihre Tabelle answers
hat keine Integrität. So wie es aussieht, können Antworten auf eine Frage aufgezeichnet werden, die der Schüler nicht gefragt wurde, oder auf einen Test, bei dem der Schüler nicht saß. Die Vermeidung dieses Fehlertyps ist ein gewöhnlicher Tarif in einer relationalen Datenbank und in einem Datensatzanmeldungssystem nicht möglich.
In diesen dunklen Tagen der IT ist dies ein allgemeiner Trend. Menschen konzentrieren sich auf die Daten -Werte ; Sie stellen sich die -Werte in Tabellenform vor und sie gehen direkt zum implementierenden Objekt, das diese -Werte enthält . Anstatt die Daten zu verstehen und was es bedeutet.
answers(stud_id, que_id, answer)
hat keine Bedeutung, keine Integrität, es sei denn, der Kontext eines student_test wird bestätigt.
Das dritte Element ist kein Fehler, weil Sie es nicht als Voraussetzung angegeben haben. Es scheint mir jedoch, dass eine Frage in mehr als einem Test verwendet werden kann. Wie Sie es eingerichtet haben, werden solche Fragen dupliziert (der ganze Sinn einer Datenbank besteht darin, sie zu normalisieren, so dass es keine Duplizierung gibt).
test_question.
Auf diese Weise können Antworten gespeichert werden, aber sie erhöhen die Anzahl der Datensätze, da für jede vom Schüler gelöste Frage ein neuer Datensatz in der Antworttabelle hinzugefügt wird.
Ja. Das ist normal für eine Datenbank.
Gibt es einen besseren Weg, dies zu tun, wenn die Anzahl der Datensätze geringer ist.
Für ein Record Filing System, ja. Für eine Datenbank, nein. Da Sie Ihre Frage als Datenbank-Design markiert haben, gehe ich davon aus, dass Sie das wollen.
Eine Datenbank ist eine Sammlung von Fakten, nicht von Datensätzen mit verwandten Feldern. Die Fakten beziehen sich auf die reale Welt, beschränkt auf den Umfang der Datenbank und App.
Es ist wichtig, die diskreten Fakten zu bestimmen, die wir brauchen, weil untergeordnete Fakten von Fakten höherer Ordnung abhängen. Das ist Datenbank-Design. Und wir normalisieren die Daten, während wir Fortschritte machen, als Teil ein und derselben Übung. Normalisierung hat den Zweck, Duplikate zu eliminieren, ansonsten haben Sie Update Anomalien. Und wir bestimmen relationale Schlüssel, wenn wir Fortschritte machen, wieder als Teil ein und derselben Übung. Relationale Schlüssel stellen die logische Struktur einer relationalen Datenbank dar, d. die logische Integrität.
z.B. Ein Test besteht aus 100 Fragen und 1000 Studenten machen diesen Test, für jeden Studenten gibt es 100 Datensätze für jede Frage und für 1000 Studenten 100k Datensätze.
Ja. Aber das drückt sich in den ISAM-Satzverarbeitungsbedingungen aus. In Bezug auf die Datenbank können Sie nicht die Tatsache umgehen, dass die Datenbank speichert:
Fakten über 100 Fragen
Fakten über 1.000 Studenten
Fakten über 1.000 Studenten mal die 100 Entscheidungen, die sie getroffen haben
Sie müssen sich mit zwei Dingen beschäftigen: mit der großen Anzahl von diskreten Fakten; und die Verwendung von zusammengesetzten Schlüsseln. Beide sind wichtig für relationale Datenbanken. Wenn einer dieser Faktoren fehlt oder Sie ihn widerstrebend implementieren, haben Sie nicht die Integrität, Leistung oder Geschwindigkeit einer relationalen Datenbank. Sie verfügen über ein ISAM-Registrierungssystem vor 1970.
Außerdem sind die SQL-Plattformen und bis zu einem gewissen Grad die NONsql-Plattformen wie myNONsql stark für die Verarbeitung von Datensätzen optimiert (nicht Datensatz für Datensatz). Schweres I / O und Caching; usw. Wenn Sie die Strukturen implementieren, die für hohe Parallelität erforderlich sind, erhalten Sie noch mehr Leistung.
Was die Implementierung und insbesondere die Leistung angeht, gibt es Fehler. Eine Neuformulierung wäre, die Implementierung sollte nicht versucht werden, bis die Daten richtig verstanden und modelliert sind.
Das Problem auf der ganzen Linie besteht darin, dass Sie ein Ersatzzeichen hinzugefügt haben (es gibt keinen "Ersatzschlüssel", es ist einfach ein Ersatzzeichen, eine physische Datensatz-ID).Es ist viel zu früh in der Modellierung; es ist nicht genug fortgeschritten; das Modell ist nicht stabil, um Surrogate hinzuzufügen.
Surrogate sind immer eine zusätzliche Spalte und der zugrunde liegende Index. Offensichtlich verbraucht das Ressourcen und hat Kosten für Einfügen und Löschen.
Surrogate bieten keine Zeileneindeutigkeit , die in einer relationalen Datenbank verlangt wird.
Das relationale Modell verlangt, dass Keys aus den Daten bestehen. Relationale Schlüssel bieten Zeileneindeutigkeit.
Ein Surrogat besteht nicht aus den Daten. Daher ist es kein relationaler Schlüssel und bietet keine der Eigenschaften eines.
Wenn ein Ersatzzeichen verwendet wird, ersetzt es nicht den Schlüssel, es ist zusätzlich für den Schlüssel. Deshalb evaluieren wir die Notwendigkeit von Surrogaten erst nach der Modellierung der Daten. Es handelt sich um eine Implementierung, nicht um eine Modellierung.
Lassen Sie mich lieber den Vorschlag vorlegen, als dass ich vor und zurück gehe, und Sie können darüber diskutieren.
Student-Testdatenmodell (Nur Seite 1, für diejenigen, die der Progression folgen).
Wenn Sie nicht an die Notation gewöhnt sind, beachten Sie bitte, dass jedes kleine Häkchen, jede Kerbe und jede Markierung, die feste vs. gestrichelte Linie, das Quadrat vs. runde Ecken, etwas sehr Spezifisches bedeutet. Siehe IDEF1X-Notation .
> Für test
und question.
habe ich id
Spalten übrig gelassen, aber beachten Sie, dass Sie mit kurzen, aussagekräftigen Codes viel besser dran sind.
student_id
ist gültig, weil sowohl name
als auch email
zu groß sind, um zu den untergeordneten Tabellen zu migrieren.
Bitte überprüfen Sie die Verb Phrases sorgfältig, sie enthalten eine Reihe von Prädikaten. Der Rest der Prädikate kann direkt aus dem Modell bestimmt werden. Wenn dies nicht klar ist, fragen Sie bitte.
Sehen Sie, ob Sie feststellen können, dass dies eine Sammlung von Fakten ist, und jede Tatsache ist diskret, weil andere Fakten davon abhängen; Es handelt sich nicht um eine Sammlung von Datensätzen mit verwandten Feldern.
Ihre Tabelle
answers
hat keine Integrität. So wie es aussieht, können Antworten auf eine Frage aufgezeichnet werden, die der Schüler nicht gefragt wurde, oder auf einen Test, bei dem der Schüler nicht saß. Die Vermeidung dieses Fehlertyps ist ein gewöhnlicher Tarif in einer relationalen Datenbank und in einem Datensatzanmeldesystem nicht möglich.
answers
, jetzt mit dem Namen student_response,
benannt, weist jetzt eine gewisse Integrität auf. A student
wird für einen Test in student_test,
registriert und student_responses
sind auf student_test.
beschränkt.
Bitte kommentieren / diskutieren.
Ich werde ein zusätzliches Tabellenobjekt (subject_id, subject_name) hinzufügen und dieses subject_id in der fraglichen Tabelle als FK hinzufügen, ist das okay?
Ja, auf jeden Fall. Aber das hat Konsequenzen. Einige Ratschläge, um sicherzustellen, dass wir das richtig machen, auf der ganzen Linie:
Wie bereits erwähnt, verwenden Sie keine Surrogate (Record IDs), es sei denn, Sie müssen dies unbedingt tun. Funktionscodes sind für Bezeichner sowohl für Benutzer als auch für Entwickler viel besser.
ID
-Spalten wünschen, lesen Sie diese Antwort . Betreff ist wichtig. Es ist der Kontext, in dem (a) ein question
existiert und (b) ein test
existiert. Sie existierten als unabhängige Elemente (Seite 1 des DM), aber jetzt sind sie dem subject.
untergeordnet. Der Zusatz verbessert die Datenintegrität erheblich.
Die Tatsache einer Studentenregistrierung und die Tatsache, dass ein Student für einen Test sitzt, sind diskrete und separate Fakten.
Dankbarerweise wurden die beiden Surrogate question_id
und test_id.
Short codes
wie CHAR(2)
einfacher und aussagekräftiger.
Beachten Sie die Verbesserung der Tabellennamen, verbesserte Übersichtlichkeit.
Ich habe das Student Test Data Model (nur für diejenigen, die der Progression folgen).
Das macht jedoch etwas aus (deshalb modellieren wir Daten, Papier ist billig, viele Entwürfe sind normal). Wenn wir die Prädikate auswerten (wie im ausführlich beschrieben) IDEF1X Notation Dokument):
%Vor% diese Prädikate sind nicht genau.A student
kann für ein test
in einem beliebigen subject.
sitzen. Angesichts der neuen Tabelle subject
würde ich denken, dass students
für subjects,
registriert werden soll und daher student_test
auf% beschränkt werden soll. co_de%, für die subjects
registriert ist.
Ich habe das Testdatenmodell für Studenten aktualisiert (Seite 3). Jetzt haben wir noch mehr Integrität, so dass student
auf student_test
beschränkt ist, für die subjects
registriert ist. Die relevanten Prädikate sind:
Nun scheint das Datenmodell vollständig zu sein.
Kontext ist alles in einer Datenbank.
Die Datenhierarchien sind beim Zusammensetzen der Schlüssel deutlich sichtbar.
Beachten Sie, dass es die relationalen Schlüssel in den untergeordneten Tabellen sind, die relationale Integrität mit den übergeordneten Tabellen für jede höhere Ebene (Eltern, Großelternteil) in der Hierarchie bereitstellen.
Falls es nicht offensichtlich ist, beachte die Macht von Relational Joins. Etwas, was Sie nicht mit Record Filing Systems tun können, die student
Felder in jeder Datei haben. ZB:
Trete ID
direkt mit student_response
auf subject
bei, ohne zwischen den beiden Ebenen navigieren zu müssen
Trete subject_code
direkt mit student_response
auf student
bei, ohne zwischen den beiden Ebenen navigieren zu müssen
Nein, es gibt kein besseres Design, weil das Design nichts damit zu tun hat, wie viele Datensätze in den Tabellen enthalten sind. Sie werden das gleiche Design wählen, egal, ob Sie mit zehn Studenten oder zehntausend beschäftigen.
Ihr Tischdesign sieht gut aus. Mach dir keine Sorgen über die Anzahl der Datensätze. Ein dbms wird erstellt, um mit großen Tabellen umzugehen. Und 100k Datensätze ist immer noch eine kleine Datenbank. Ich würde diesen Entwurf nicht einmal ändern, wenn es Milliarden von zu speichernden Antworten gäbe.
Wenn Sie die Daten normalisieren möchten, dann würde ich die Tabellen etwas anders erstellen.
Ihr Schülertisch sieht gut aus. Im Allgemeinen verwende ich einen singulären Namen für Tabellen statt Plural.
%Vor%Hier ist die Testtabelle:
%Vor%Wir binden Studenten an Tests mit einer Junction-Tabelle.
%Vor%Die Zeit und die Länge des Tests variieren von Schüler zu Schüler, daher sind diese Spalten in der StudentTest-Tabelle enthalten.
Die Fragetabelle.
%Vor%Und die Antworttabelle.
%Vor%Hier werden die Dinge schwierig. Sie können einem Test auf der Grundlage der ID Fragen zuweisen, so.
%Vor%Aber wenn Sie das tun und jemand den Fragetext nach dem Test ändert, zeigt die Fragen-ID auf eine andere Frage als die Frage zum Test.
Um dieses Problem zu lösen, erstellen wir Historietabellen wie folgt:
%Vor%Also erstellen wir die TestQuestion-Tabelle wie folgt:
%Vor%Und kopieren Sie die Fragen sowie die Antworten auf die Verlaufstabellen.
Aus ähnlichen Gründen erstellen wir die QuestionAnswer-Tabelle wie folgt:
%Vor%Ihr Code könnte sicherstellen, dass jede Frage vier mögliche Antworten enthält. Die Datenbank ermöglicht mehr oder weniger als 4 mögliche Antworten.
Schließlich binden wir die Antworten des Schülers an die Testfragen.
%Vor%Ja, die Spalte Test-ID ist hier doppelt vorhanden. Dies ist so, dass Sie sowohl den Test als auch den Schüler, der den Test gemacht hat, abfragen können.
Das Feld "Is Is Correct" hat in der Tabelle "QuestionAnswer" und in der Tabelle "StudentQuestionAnswer" eine andere Bedeutung. In der QuestionAnswer-Tabelle zeigt der Boolesche Wert "Is Correct Answer" auf die richtige Antwort. In der Tabelle "StudentQuestionAnswer" gibt der Boolean "Is Correct Answer" an, dass der Schüler die Frage korrekt beantwortet hat.
Dies sollte eine vollständige Frage / Antwort-Datenbank sein. Sie können Tests an Kurse binden, wenn Sie möchten.
Sie können die Details für die Antwort als einen ~ getrennten Datensatz für die entsprechende Frage-ID speichern, die auch ein ~ getrennt ist. Auf diese Weise wird es für eine Studenten-ID nur einen Datensatz geben. Sie können die ANS auch für eine bestimmte Fragen-ID dekodieren
Sehen Sie sich diesen Link an. Dies könnte Ihnen helfen, ähnliche Lösungen zu entwickeln.
Tags und Links mysql database database-design