Mysql
 sql >> Datenbank >  >> RDS >> Mysql

So speichern Sie Daten, deren Typ numerisch, Datum oder Zeichenfolge in MySQL sein kann

Ich habe keine formelle Studie durchgeführt, aber aus meiner eigenen Erfahrung würde ich schätzen, dass mehr als 80 % der Fehler im Datenbankdesign auf das Design mit Leistung als wichtigster (wenn nicht einziger) Überlegung zurückzuführen sind.

Wenn ein gutes Design mehrere Tabellen erfordert, erstellen Sie mehrere Tabellen. Gehen Sie nicht automatisch davon aus, dass Joins vermieden werden sollten. Sie sind selten die wahre Ursache von Leistungsproblemen.

Die wichtigste Überlegung, in erster Linie in allen Phasen des Datenbankdesigns, ist die Datenintegrität. „Die Antwort ist vielleicht nicht immer richtig, aber wir können sie Ihnen sehr schnell zukommen lassen“ ist kein Ziel, auf das jeder Shop hinarbeiten sollte. Sobald die Datenintegrität gesperrt wurde, wenn die Leistung jemals zu einem Problem wird , es kann angesprochen werden. Opfern Sie nicht die Datenintegrität, insbesondere um Probleme zu lösen, die möglicherweise gar nicht existieren.

Schauen Sie sich in diesem Sinne an, was Sie brauchen. Sie haben Beobachtungen, die Sie speichern müssen. Diese Beobachtungen können in der Anzahl und Art der Attribute variieren und können unter anderem Dinge wie der Wert einer Messung, die Benachrichtigung über ein Ereignis und die Änderung eines Status sein, mit der Möglichkeit, zukünftige Beobachtungen hinzuzufügen.

Dies scheint in ein Standardmuster „Typ/Subtyp“ zu passen, wobei der Eintrag „Beobachtung“ der Typ und jeder Typ oder jede Art von Beobachtung der Subtyp ist, und schlägt eine Art Typindikatorfeld vor, wie z. B.:

create table Observations(
   ...,
   ObservationKind  char( 1 ) check( ObservationKind in( 'M', 'E', 'S' )),
   ...
);

Aber das Festkodieren einer Liste wie dieser in einer Check-Einschränkung hat ein sehr geringes Wartbarkeitsniveau. Es wird Teil des Schemas und kann nur mit DDL-Anweisungen geändert werden. Nichts, worauf sich Ihr DBA freuen wird.

Haben Sie also die Arten von Beobachtungen in ihrer eigenen Nachschlagetabelle:

ID  Name         Meaning
==  ===========  =======
M   Measurement  The value of some system metric (CPU_Usage).
E   Event        An event has been detected.
S   Status       A change in a status has been detected.

(Das char-Feld könnte genauso gut int oder smallint sein. Ich verwende hier char zur Veranschaulichung.)

Füllen Sie dann die Beobachtungstabelle mit einem PK und den Attributen aus, die allen Beobachtungen gemeinsam sind.

create table Observations(
   ID               int identity primary key,
   ObservationKind  char( 1 ) not null,
   DateEntered      date not null,
   ...,
   constraint FK_ObservationKind foreign key( ObservationKind )
      references ObservationKinds( ID ),
   constraint UQ_ObservationIDKind( ID, ObservationKind )
);

Es mag seltsam erscheinen, einen eindeutigen Index für die Kombination aus Kind-Feld und PK zu erstellen, was an sich schon eindeutig ist, aber haben Sie einen Moment Geduld.

Jetzt bekommt jede Art oder Unterart eine eigene Tabelle. Beachten Sie, dass jede Art von Beobachtung eine Tabelle erhält, nicht den Datentyp.

create table Measurements(
    ID                   int not null,
    ObservationKind      char( 1 ) check( ObservationKind = 'M' ),
    Name                 varchar( 32 ) not null, -- Such as "CPU Usage"
    Value                double not null, -- such as 55.00
    ...,  -- other attributes of Measurement observations
    constraint PK_Measurements primary key( ID, ObservationKind ),
    constraint FK_Measurements_Observations foreign key( ID, ObservationKind )
        references Observations( ID, ObservationKind )
);

Die ersten beiden Felder sind für die anderen Arten von Beobachtungen gleich, außer dass die Check-Einschränkung den Wert auf die entsprechende Art erzwingt. Die anderen Felder können sich in Nummer, Name und Datentyp unterscheiden.

Sehen wir uns ein Beispiel-Tupel an, das in der Maßtabelle vorhanden sein könnte:

ID    ObservationKind  Name       Value  ...
====  ===============  =========  =====
1001  M                CPU Usage  55.0   ...

Damit dieses Tupel in dieser Tabelle vorhanden ist, muss zuerst ein übereinstimmender Eintrag in der Beobachtungstabelle mit einem ID-Wert von 1001 und einem Beobachtungsartwert von 'M' vorhanden sein. Kein anderer Eintrag mit einem ID-Wert von 1001 kann weder in der Beobachtungstabelle noch in der Messungstabelle existieren und kann überhaupt nicht in irgendeiner anderen der "Art"-Tabellen (Ereignisse, Status) existieren. Dies funktioniert für alle Art-Tabellen auf die gleiche Weise.

Ich würde außerdem empfehlen, für jede Art von Beobachtung eine Ansicht zu erstellen, die eine Verbindung jeder Art mit der Hauptbeobachtungstabelle bereitstellt:

create view MeasurementObservations as
    select ...
    from   Observations o
    join   Measurements m
        on m.ID = o.ID;

Jeder Code, der ausschließlich mit Messungen arbeitet, müsste nur diese Ansicht anstelle der zugrunde liegenden Tabellen treffen. Die Verwendung von Ansichten zum Erstellen einer Abstraktionswand zwischen dem Anwendungscode und den Rohdaten verbessert die Wartbarkeit der Datenbank erheblich.

Nun erfordert die Erstellung einer anderen Art von Beobachtung, wie z. B. „Error“, eine einfache Insert-Anweisung für die ObservationKinds-Tabelle:

F   Fault        A fault or error has been detected.

Natürlich müssen Sie eine neue Tabelle und Ansicht für diese Fehlerbeobachtungen erstellen, aber dies hat keine Auswirkungen auf vorhandene Tabellen, Ansichten oder Anwendungscode (außer natürlich, um den neuen Code zu schreiben, um mit den neuen Beobachtungen zu arbeiten). .