Optimierung der Datenbankstruktur

8

Ich entwickle ein Belohnungssystem für unsere VLE, ​​das drei verschiedene Technologien verwendet: JavaScript für die meisten Client-Side / Display-Prozesse, PHP für die Kommunikation mit der Datenbank und MySQL für die Datenbank selbst.

Ich habe drei Screenshots meiner Tabelle "transactions" beigefügt. Seine Struktur, einige Beispieldaten und eine Übersicht seiner Details.

Die Prämisse ist, dass Mitarbeiter Punkte für gutes Benehmen an Schüler vergeben. Dies kann bedeuten, dass Klassen von 30 Schülern gleichzeitig Punkte bekommen. Die Mitarbeiter haben ein Limit von 300 Punkten pro Woche und es gibt derzeit 85 Mitarbeiter, die auf das System zugreifen (dies könnte steigen).

So wie ich es momentan mache, hat jede "Transaktion" eine "Giver_ID" (der Mitarbeiter, der Punkte vergibt), eine "Recipient_ID" (der Schüler, der die Punkte erhält), eine Kategorie und einen Grund. Auf diese Weise setze ich jedesmal, wenn ein Mitarbeiter 30 Punkte ausgibt, 30 Zeilen in die Datenbank.

Dies schien früh zu funktionieren, aber innerhalb von drei Wochen habe ich bereits über 12.000 Transaktionen in der Datenbank.

An diesem Punkt wird es ein bisschen komplizierter. Auf der Seite "Punkte zuweisen" (ein weiterer Screenshot im Anhang) möchte ich, wenn ein Lehrer in eine seiner Klassen klickt oder nach einem einzelnen Schüler sucht, die Punkte der Schüler anzeigen. Die einzige Möglichkeit, dies auf meinem System zu tun, besteht darin, ein " SELECT * FROM 'transactions' " zu machen und alle Informationen in ein Array unter Verwendung des folgenden JS zu schreiben:

%Vor%

Wenn Sie sich intern beim System anmelden, scheint dies schnell genug zu funktionieren. Wenn Sie sich jedoch extern anmelden, dauert dieser Vorgang etwa 20 Sekunden. Daher werden die Punktewerte der Schüler erst angezeigt, wenn Sie einige Male geklickt / gesucht haben.

Ich verwende den folgenden Code in meinem PHP, um auf diese Transaktionen zuzugreifen:

%Vor%

Also, meine Frage ist, wie sollte ich mich dem nähern? Volltextindizes; vielleicht eine Schüler-Tabelle mit ihren Gesamtpunkten, die jedes Mal aktualisiert wird, wenn eine Transaktion eingegeben wird; Massentransaktionen (d. h. mehr als ein Student, der die gleichen Punkte für die gleiche Kategorie erhält), gruppiert in eine einzelne Datenbankzeile? Das sind alles Dinge, über die ich nachgedacht habe, aber ich würde jemanden mit mehr DB-Wissen als Erleuchtung lieben.

Beispieldatensätze

Tabellenstruktur

Tabellenübersicht

Punkte zuweisen-Schnittstelle

Vielen Dank im Voraus.

    
dunc 04.10.2011, 15:29
quelle

3 Antworten

3

Ihr Problem ist Ihre Frage:

%Vor%

Wenn Ihr Datensatz größer wird, dauert das Laden länger und es wird mehr Speicher benötigt, um es zu speichern. Bestimmen Sie vielmehr, welche Daten Sie speziell benötigen. Wenn es für einen bestimmten Benutzer ist:

%Vor%

Oder wenn Sie alle Summen für alle Ihre Schüler wollen:

%Vor%

Um die Auswahl für ein bestimmtes Feld zu beschleunigen, können Sie einen Index für dieses Feld hinzufügen. Dies wird die Auswahl beschleunigen, besonders wenn die Tabelle wächst.

%Vor%

Oder wenn Sie eine paginierte Liste aller Einträge in transactions anzeigen möchten:

%Vor%     
Tom 04.10.2011, 15:41
quelle
2

Wenn Sie Toms Vorschlag hinzufügen, sollten Sie eine weitere Normalisierung Ihrer Datenbank in Betracht ziehen. Ich nehme an, Sie haben jetzt 3 Tabellen:

students (id, name, ...)

staff (id, name, ...)

transactions (id, student_id, staff_id, points, date, reason)

Ein normalisierteres Formular verwendet mehr Tabellen mit weniger Daten:

students (id, name, ...)

staff (id, name, ...)

transactions (id, staff_id, points, date, reason)

transactions_students (transaction_id, student_id)

Das Hinzufügen einer Transaktion wird dann zu einem zweistufigen Prozess: Zuerst erstellen Sie einen Transaktionsdatensatz und anschließend fügen Sie mehrere Datensätze in transactions_students ein, wobei jeder die Transaktion mit einem Studenten verknüpft. Beachten Sie, dass Sie eine Ansicht erstellen können, die sich genau wie die ursprüngliche denormalisierte Tabelle zum Auswählen verhält, etwa wie folgt:

%Vor%

Dadurch wird die Anzahl der Datensätze in der Transaktionstabelle drastisch reduziert, und es wird vermieden, das Datum und den Grund redundant zu speichern. Der Nachteil besteht darin, dass die Verknüpfung von Transaktionen mit Studenten eine zusätzliche Verknüpfung erfordert. Wenn Sie jedoch Ihre Fremdschlüssel und -indizes ordnungsgemäß eingerichtet haben, muss dies kein Problem sein.

    
tdammers 04.10.2011 15:48
quelle
1

Ich würde die Recipient_ID indizieren, so dass Sie zu einem beliebigen Zeitpunkt gezielt nach einer Person suchen oder Ihre Daten effektiver gruppieren können. Wenn Sie sich entscheiden, nach category_id zu gruppieren, würde ich auch einen separaten oder kombinierten Index zu category_id hinzufügen.

Der zweite Vorschlag wäre, Ihre Daten im laufenden Betrieb zu gruppieren und zu aggregieren. Zum Beispiel:

%Vor%

Diese beiden Vorschläge sollten Ihre Leistung dramatisch verbessern, denn anstatt die Gesamtpunkte für Ihre Schüler auf der PHP / JS-Seite zu berechnen, tun Sie dies direkt in der Datenbank.

    
Mathieu Dumoulin 04.10.2011 15:43
quelle

Tags und Links