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

Datenbankschema verwirrend (Index und Constraints)

Ich würde den zweiten Ansatz bevorzugen. Indem Sie Ersatz-ID-Nummern verwenden, wenn sie für die Identifizierung logisch nicht erforderlich sind, führen Sie obligatorischere Joins ein. Dies erfordert, dass Sie "ID-Nummern in der gesamten Datenbank verfolgen", was das SQL-Äquivalent zu "Zeigern in der gesamten Datenbank verfolgen" ist. Das Verfolgen von Zeigern war charakteristisch für IMS, eine der Datenbankarchitekturen, die das relationale Modell ersetzen sollte. (IMS verwendet eine hierarchische Architektur.) Es hat keinen Sinn, es heute neu zu erfinden. (Obwohl eine Viel der Leute tun genau das.)

Wenn Sie beispielsweise fünf Ebenen von Ersatz-ID-Nummern haben und den Namen einer Person möchten, müssen Sie vier Joins durchführen, um ihn zu erhalten. Beim zweiten Ansatz benötigen Sie nur einen Join. Wenn Sie keine Mehrspaltenverknüpfungen schreiben möchten, verwenden Sie CREATE VIEW und tun Sie dies nur einmal.

Die Leistung ist einfach zu testen . Generieren Sie einfach ein paar Millionen zufällige Zeilen mit Ihrer bevorzugten Skriptsprache und laden Sie sie auf einen Testserver. Sie finden nicht nur heraus, wo sich Ihre Performance-Probleme verstecken, Sie finden alle Fehler in Ihrem CREATE TABLE-Code. (Ihr Code wird so wie er ist nicht funktionieren.) Erfahren Sie mehr über EXPLAIN falls du es noch nicht weißt.

Was die Indizierung betrifft , können Sie dies an den zufälligen Zeilen testen, die Sie generieren und laden. Ein mehrspaltiger Index für (Vorname, Nachname) funktioniert am besten, wenn Benutzer immer einen Vornamen angeben. Viele Benutzer tun dies jedoch nicht und suchen stattdessen lieber nach dem Nachnamen. Ein mehrspaltiger Index für (Vorname, Nachname) ist für Benutzer, die lieber nach Nachnamen suchen, nicht effektiv. Das kannst du testen.

Allein aus diesem Grund ist die Indexierung von Vor- und Nachnamen üblich effektiver, wenn es zwei getrennte Indexe gibt, einen für den Vornamen und einen für den Nachnamen.

Was bedeutet Jagd nach ID-Nummern meinst du?

Das unausgesprochene Entwurfsmuster, das dieser Frage zugrunde liegt, lautet:„Jede Zeile muss eine ID-Nummer haben, und alle Fremdschlüssel müssen auf die ID-Nummer verweisen.“ In einer SQL-Datenbank ist es eigentlich ein Anti-Pattern. Als Faustregel gilt, dass jedes Muster, mit dem Sie Tabellen entwerfen können, ohne über Schlüssel nachzudenken, als schuldig angesehen werden sollte, bis seine Unschuld bewiesen ist – es sollte als Anti-Muster angesehen werden, bis bewiesen wird, dass es nicht der Fall ist.

create table A (
 a_id integer primary key,
 a_1 varchar(15) not null unique,
 a_2 varchar(15) not null
);

create table B (
  b_id integer primary key
  a_id integer not null references A (a_id),
  b_1  varchar(10) not null,
  unique (a_id, b_1),
);

create table C (
  c_id integer primary key,
  b_id integer not null references B (b_id),
  c_1 char(3) not null,
  c_2 varchar(20) not null,
  unique (b_id, c_1)
);

create table D (
  d_id integer primary key,
  c_id integer not null references C (c_id),
  d_1 integer not null,
  d_2 varchar(15),
  unique (c_id, d_1)
);

Wenn Sie einen Bericht über Tabelle "D" benötigen und der Bericht

benötigt
  • Spalten D.d_1 und D.d_2 und
  • Spalten A.a_1 und A.a_2,

Sie benötigen 3 Joins, um dorthin zu gelangen. (Probieren Sie es aus.) Sie jagen ID-Nummern. (Wie das Verfolgen von Zeigern in IMS.) Die folgende Struktur ist anders.

create table A (
 a_1 varchar(15) primary key,
 a_2 varchar(15) not null
);

create table B (
  a_1 varchar(15) not null references A (a_1),
  b_1  varchar(10) not null,
  primary key (a_1, b_1),
);

create table C (
  a_1 varchar(15) not null,
  b_1 varchar(10) not null,
  c_1 char(3) not null,
  c_2 varchar(20) not null,
  primary key (a_1, b_1, c_1),
  foreign key (a_1, b_1) references B (a_1, b_1)
);

create table D (
  a_1 varchar(15) not null,
  b_1 varchar(10) not null,
  c_1 char(3) not null,
  d_1 integer not null,
  d_2 varchar(15),
  primary key (a_1, b_1, c_1, d_1),
  foreign key (a_1, b_1, c_1) references C (a_1, b_1, c_1)
);

Bei dieser Struktur benötigt derselbe Bericht einen einzigen Join.

select D.d_1, D.d_2, A.a_1, A.a_2
from D
inner join A on D.a_1 = A.a_1;