8

Ich bin gerade in eine interessante Situation über Beziehungen und Datenbanken geraten. Ich schreibe eine Ruby-App und für meine Datenbank verwende ich postgresql. Ich habe ein Elternobjekt "Benutzer" und ein verwandtes Objekt "Dings", wo ein Benutzer ein oder mehrere Dinger haben kann. Was wäre der Vorteil der Verwendung einer separaten Tabelle gegenüber dem Einbetten von Daten in ein Feld in der übergeordneten Tabelle?Warum in der Welt hätte ich viele Beziehungen?

Beispiel von Active:

einer Bezugstabelle unter Verwendung von:

def change 
    create_table :users do |i| 
     i.text :name 
    end 
    create_table :thingies do |i| 
     i.integer :thingie 
     i.text :discription 
    end 
end 
class User < ActiveRecord::Base 
    has_many :thingies 
end 
class Thingie < ActiveRecord::Base 
    belongs_to :user 
end 

ein eingebettetes Datenstruktur (mehrdimensionales Array) Methode:

def change 
    create_table :users do |i| 
     i.text :name 
     i.text :thingies, array: true # example contents: [[thingie,discription],[thingie,discription]] 
    end 
end 
class User < ActiveRecord::Base 
end 

Relevante Informationen

Ich bin uns heroku und heroku-posgres als meine Datenbank. Ich verwende ihre freie Option, die mich auf 10.000 Zeilen beschränkt. Dies scheint mich dazu zu bringen, den multidimensionalen Array-Weg zu benutzen, aber ich weiß es nicht wirklich.

+0

http://stackoverflow.com/questions/27257093/rails-use-serialized-attributes-or-belongs-to-association –

+0

@LannyBose Nein, das ist eine andere Frage. Das ist über Serialisierung vs. has_many, und ich hätte dieses Problem nicht, weil ich ein mehrdimensionales Array verwenden würde. Diese Antwort wäre keine Antwort für mich, und die Frage ist anders als meine. – thesecretmaster

+0

Ah ... Entschuldigung. :( –

Antwort

11

Das Einbetten einer Datenstruktur in ein Feld kann in einfachen Fällen funktionieren, verhindert jedoch, dass Sie relationale Datenbanken ausnutzen. Relationale Datenbanken sind darauf ausgelegt, Ihre Daten zu finden, zu aktualisieren, zu löschen und zu schützen. Mit einem eingebetteten Feld, das eigene Wad-O-Daten (Array, JSON, XML usw.) enthält, schreiben Sie den gesamten Code, um dies selbst zu tun.

Es gibt Fälle, in denen das eingebettete Feld besser geeignet sein könnte, aber für diese Frage werde ich als Beispiel einen Fall verwenden, der die Vorteile einer verwandten Tabelle aufzeigt.

Stellen Sie sich ein Benutzer- und Post-Beispiel für ein Blog vor.

Für eine eingebettete Post Lösung, würden Sie eine Tabelle so etwas wie diese (psuedocode - das ist wahrscheinlich nicht gültig DDL) haben:

create table Users { 
id int auto_increment, 
name varchar(200) 
post text[][], 
} 

Mit verknüpften Tabellen, Sie so etwas wie

create table Users { 
id int auto_increment, 
name varchar(200) 
} 
create table Posts { 
id auto_increment, 
user_id int, 
content text 
} 
tun würden

Object Relational Mapping (ORM) -Tools: Mit dem eingebetteten Post schreiben Sie den Code manuell, um einem Benutzer Posts hinzuzufügen, durch vorhandene Posts zu navigieren, sie zu validieren, zu löschen usw. Mit der separaten Tabelle de Zeichen, können Sie die ActiveRecord (oder welches objektrelationale System, das Sie verwenden) Werkzeuge für diese verwenden, die Ihren Code viel einfacher halten sollten.

Flexibilität: Stellen Sie sich vor, Sie möchten dem Beitrag ein Datumsfeld hinzufügen. Sie können dies mit einem eingebetteten Feld tun, aber Sie müssen Code schreiben, um Ihr Array zu analysieren, die Felder zu validieren, die vorhandenen eingebetteten Beiträge zu aktualisieren usw. Mit der separaten Tabelle ist dies viel einfacher. Nehmen wir einmal an, Sie möchten Ihrem System einen Editor hinzufügen, der alle Beiträge genehmigt. Mit dem relationalen Beispiel ist das einfach. Als Beispiel alle Beiträge von ‚Bob‘ mit Active bearbeitet finden, würden Sie brauchen nur:

Editor.where(name: 'Bob').posts 

Für die Seite eingebettet sind, würden Sie Code schreiben müssen durch jeden Benutzer in der Datenbank zu gehen, analysieren jeden ihrer Beiträge und suchen Sie im Editorfeld nach 'Bob'.

Leistung: Stellen Sie sich vor, Sie haben 10.000 Benutzer mit durchschnittlich 100 Posts. Jetzt möchten Sie alle Beiträge finden, die an einem bestimmten Datum gemacht wurden. Mit dem eingebetteten Feld müssen Sie jeden Datensatz durchlaufen, das gesamte Array aller Posts parsen, die Daten extrahieren und den gewünschten Datensatz überprüfen. Dies wird sowohl cpu und Festplatte i/0 kauen. Für die Datenbank können Sie einfach das Datumsfeld indizieren und die exakten Datensätze herausziehen, die Sie benötigen, ohne jeden Beitrag von jedem Benutzer zu analysieren.

Standards: Durch die Verwendung einer herstellerspezifischen Datenstruktur kann das Verschieben Ihrer Anwendung in eine andere Datenbank ein Problem darstellen. Postgres scheint eine Vielzahl von Datentypen zu haben, aber sie sind nicht identisch mit MySQL, Oracle, SQL Server usw. Wenn Sie bei Standarddatentypen bleiben, werden Sie viel leichter Backends austauschen können.

Das sind die Hauptprobleme, die ich von oben sehe. Ich habe diesen Fehler gemacht und den Preis dafür bezahlt, also wenn es keinen überzeugenden Grund gäbe, würde ich den separaten Tisch benutzen.

2

Was ist, wenn Benutzer John und Ann die gleichen Dinger haben? Die Datensätze werden dupliziert, und wenn Sie sich entscheiden, den Namen der Sache zu ändern, müssen Sie zwei oder mehr Datensätze ändern. Wenn in der separaten Tabelle etwas gespeichert ist, müssen Sie nur einen Datensatz ändern. FYI https://en.wikipedia.org/wiki/Database_normalization

2

Vorteile von einem zu vielen:

  1. Einfachere ORM (Object Relational Mapping) Integration. Sie können es in beide Richtungen verwenden, aber Sie müssen Ihre Tabellen mit nativen SQL definieren. Unterschiedliche Tabellen sind einfacher und Sie können automatisch generierte Zuordnungen verwenden.
  2. Ihre Speicherplatzbeschränkung von 10.000 Zeilen wird weiter mit der Eins-zu-viele-Beziehung gehen, falls 2 oder mehr Personen die gleichen "Dings" haben können.
  3. Benutzer und Dinger getrennt behandeln. In einigen Fällen interessieren Sie sich vielleicht nur für Menschen oder Dinger, nicht für ihre Beziehung zueinander. Einige Beispiele, um einen Benutzernamen oder eine Beschreibung zu aktualisieren, um eine Liste aller Dings (oder aller Benutzer) zu erhalten. Die Auswahl aus der einzelnen Tabelle kann die Zusammenarbeit erschweren.
  4. Wartung und Manipulation ist einfacher. Für den Fall, dass ein Benutzer oder ein Ding aktualisiert wird (Namensänderung, Aktualisierung der E-Mail-Adresse usw.), müssen Sie nur 1 Datensatz in ihrer Tabelle aktualisieren, anstatt Updateanweisungen zu schreiben "where user_id =?".
  5. Durchsetzbare Datenbankbeschränkungen. Was ist, wenn ein Ding niemandem gehört? Ist die Benutzerspalte jetzt nillable? Es müsste im Fall einer einzelnen Tabelle sein, sodass Sie beispielsweise keinen einfachen "nicht nillierbaren" Benutzernamen erzwingen können.

Es gibt viele Gründe natürlich. Wenn Sie eine relationale Datenbank verwenden, sollten Sie die one to many verwenden, indem Sie Ihre Objekte (Benutzer und Din- ges) als separate Tabellen aufteilen. Wenn Sie die Begrenzung der Anzahl der Datensätze berücksichtigen und die Größe Ihres Datasets klein ist (unter 10.000), sollten Sie die Nachteile von normalisierten Daten nicht spüren.

Die kurze Wahrheit ist, dass es Vorteile von beiden gibt. Sie könnten zum Beispiel schnellere Lesezeiten aus dem Single-Table-Ansatz bekommen, weil Sie keine komplizierten Joins benötigen.

Hier ist eine gute Referenz mit den Vor-/Nachteile von beiden (normalisiert ist die Multiple-Table-Ansatz und denormalized ist der Single-Table-Ansatz). http://www.ovaistariq.net/199/databases-normalization-or-denormalization-which-is-the-better-technique/

+0

Würde ich falsch liegen, wenn ich sagte, dass meine Take-Away zu verwenden war, welcher Weg enthält weniger Duplikate oder ist DRYer? – thesecretmaster

+0

Ich werde nicht den Besitz meiner Dinger teilen. Leute können meine Dinger benutzen, aber diese Dinger werden mir noch gehören. –

1

Neben den anderen erwähnten Vorteilen gibt es auch eine Sache über Standards. Wenn Sie alleine an dieser App arbeiten, ist das kein Problem, aber wenn jemand anders etwas ändern möchte, dann beginnt der Albtraum. Es kann eine Weile dauern, bis dieser Typ versteht, wie es alleine funktioniert. Und so etwas zu verändern, wird noch mehr Zeit in Anspruch nehmen. Auf diese Weise kann eine einfache Verbesserung sehr zeitaufwendig sein. Und irgendwann wirst du mit anderen Leuten arbeiten. Also immer wie der Typ, der am Ende mit deinem Code arbeitet, ist der brutale Psychopath, der weiß, wo du lebst.