TL; DR - Sie entwerfen die Datenbank basierend darauf, wie sie in der Schule unterrichtet wurden.
Ich hätte diese Frage vor 10 Jahren schreiben können. Ich habe einige Zeit gebraucht, um zu verstehen, warum meine Vorgänger ihre Datenbanken so gestaltet haben, wie sie es getan haben. Sie arbeiten mit jemandem zusammen, der entweder:
- Sammelte die meisten Kenntnisse im Datenbankdesign mit Excel als Datenbank oder
- Sie wenden die besten Praktiken an, als sie die Schule verlassen haben.
Ich vermute nicht, dass es die Nummer 1 ist, da Sie tatsächlich ID-Nummern in Ihrer Tabelle haben, also nehme ich die Nummer 2 an.
Nachdem ich die Schule verlassen hatte, arbeitete ich für einen Laden, in dem AS / 400 (auch bekannt als IBM i) verwendet wurde. Ich fand einige seltsame Dinge in der Art und Weise, wie sie ihre Datenbanken entworfen haben, und begann zu befürworten, dass wir Änderungen vornehmen, um zu verfolgen, wie mir das Entwerfen von Datenbanken beigebracht wurde. (Ich war damals dumm)
Ein geduldiger älterer Programmierer brauchte, um mir zu erklären, warum die Dinge so gemacht wurden. Sie hatten das Schema nicht geändert, weil es dazu geführt hätte, dass Programme, die älter als ich waren, nicht mehr funktionierten. Der Quellcode für ein Programm hatte buchstäblich das Erstellungsdatum des Jahres vor meiner Geburt. Auf dem System, an dem wir arbeiteten, mussten ihre Programme alle Logik und Operationen implementieren, die der Abfrageplaner Ihrer Datenbank für Sie handhabt. (Sie können dies sehen, indem Sie EXPLAIN für eine Ihrer Abfragen ausführen.)
Er war auf dem neuesten Stand der Techniken, die ich implementieren wollte, aber es war wichtiger, das System am Laufen zu halten, als Änderungen vorzunehmen, "weil dies gegen das verstieß, was mir beigebracht wurde". Jedes neue Projekt, mit dem einer von uns begonnen hat, hat das Beziehungsmodell, das wir konnten, bestmöglich genutzt. Leider haben andere Programmierer / Berater aus dieser Zeit ihre Datenbanken immer noch so gestaltet, als würden sie mit den früheren Einschränkungen dieses Systems arbeiten.
Einige Beispiele dessen, was mir begegnet ist und nicht zum relationalen Modell passt:
- Daten wurden als julianische Tagesnummern gespeichert, für die eine Verknüpfung mit einer Datumstabelle erforderlich war, um das tatsächliche Datum zu ermitteln.
- Denormalisierte Tabellen mit sequentiellen Spalten desselben Typs (z. B.
code1,code2, ..., code20
)
- CHAR-Spalten der Länge NxM, die ein Array von N Zeichenfolgen der Länge M darstellen.
Die Gründe, die mir für diese Entwurfsentscheidungen gegeben wurden, basierten alle auf den Einschränkungen des Systems, als die Datenbank zum ersten Mal entworfen wurde.
Daten - Mir wurde mitgeteilt, dass die Verwendung von Datumsfunktionen (welcher Monat oder Tag oder Wochentag) mehr Verarbeitungszeit in Anspruch nahm als die Erstellung einer Tabelle für jedes mögliche Datum mit all diesen Informationen.
Sequentielle Spalten desselben Typs - In der Programmierumgebung, in der sie sich befanden, konnte ein Programm eine Arrayvariable über einen Teil der Zeile erstellen. Und es war eine einfachere Möglichkeit, die Anzahl der Lesevorgänge zu verringern.
CHAR-Spalten mit einer Länge von NxM - Es war einfacher, Konfigurationswerte in eine Spalte zu verschieben, um Dateilesevorgänge zu reduzieren.
Ein schlecht durchdachtes Beispiel in C, das die Programmierumgebung widerspiegelt, die sie hatten:
#define COURSE_LENGTH 4
#define NUM_COURSES 4
#define PERIOD_LENGTH 2
struct mytable {
int id;
char periodNames[NUM_COURSES * PERIOD_LENGTH]; // NxM CHAR Column
char course1[COURSE_LENGTH];
char course2[COURSE_LENGTH];
char course3[COURSE_LENGTH];
char course4[COURSE_LENGTH];
};
...
// Example row
struct mytable row = {.id= 1, .periodNames="HRP1P2P8", .course1="MATH", .course2="ENGL", .course3 = "SCI ", .course4 = "READ"};
char *courses; // Pointer used to access the sequential columns
courses = (char *)&row.course1;
for(int i = 0; i < NUM_COURSES; i++) {
printf("%d: %.*s -> %.*s\n",i+1, PERIOD_LENGTH, &row.periodNames[PERIOD_LENGTH * i], COURSE_LENGTH,&courses[COURSE_LENGTH*i]);
}
Ausgänge
1: HR -> MATH
2: P1 -> ENGL
3: P2 -> SCI
4: P8 -> READ
Nach dem, was mir gesagt wurde, galt ein Teil davon damals als best practice.