Wie erstelle ich eine Datenbank für unbekannte Arten von Daten?

7

Ich bin gerade dabei, eine Datenbank für eine neue PHP / MySql-basierte Anwendung zu entwerfen.

Mein Problem ist, dass ich nicht darstellen kann und kann, was in der Datenbank gespeichert werden soll, da es unbegrenzt ist und sich ändert.

Hier ist das Problem Beispiel: Die Anwendung wird eine Shopping - Website, dass viele Arten von Produkten , alle von ihnen haben einige gemeinsamen Attribute wie hat titleund priceaber einige Arten haben spezifische Details wie expiry dateeinige haben isbneinige nicht.

Dies ist nur ein Beispiel, aber ich habe wirklich viele Arten mit vielen verschiedenen Attributen.

Ich kann für jede Art eine Tabelle erstellen, aber ich habe nicht alle verfügbaren Arten, viele Arten von Gegenständen sind derzeit unbekannt.

Ist dies eine Möglichkeit, dieses Problem zu lösen, ohne den Benutzer zu überfordern?

malhobayyeb
quelle
4
en.wikipedia.org/wiki/Entity –attribute - value_model ist das, was Sie suchen
Philᵀᴹ
1
Ich habe eine sehr ähnliche Frage zum Stapelüberlauf gestellt: Wie entwerfe ich eine Datenbank für benutzerdefinierte Felder? . Möglicherweise möchten Sie die dort veröffentlichten Informationen überprüfen. Ich denke , das Endergebnis ich ging noch ein Tisch für alle gemeinsamen Attribute war, und dann das Benutzer - Tabellen zu machen für die Datenattribute von allgemeinen bekannten Gruppen von Einheiten (wie Books, Music, usw.) und EAV für die selteneren Datenattribute.
Rachel

Antworten:

10

Unbekannte Arten von Daten klingen für mich etwas faul. Ihre Beispiele sind natürlich alle bekannt. Für Waren und Dienstleistungen sind sorgfältige Analysen und Normalisierungen wichtig, und ich denke, Sie können sich von der EAV-Modellierung (von der ich denke, dass sie mehr Probleme verursacht als löst) für Kerndaten lösen. Der Rest könnte in XML-Felder oder ähnliches gestopft werden. Wenn Sie Ihr Design richtig machen, können Sie die Informationen außerdem jederzeit entsprechend erweitern. Betrachten Sie die folgenden drei Tabellen:

CREATE TABLE products (
    id int autoincrement primary key,
    sellprice numeric,
    part_code varchar(10),
    title varchar(32),
    description text
);

CREATE TABLE barcode_type (
    id int autoincrement primary key,
    label varchar(15) not null unique
);

CREATE TABLE make_model (
    id int autoincrement primary key,
    make varchar(15) not null,
    model varchar(15),
    barcode_type int references barcode_type(id),
    barcode varchar(32)
);

Jetzt können Sie verschiedenen Teilen Barcodes (einschließlich ISBN, EAN, UPC usw.) zuweisen, einen pro Marke / Modell-Kombination. Wenn Sie mehr Barcode-Typen unterstützen müssen, ist dies nicht schwer hinzuzufügen. Wohin diese gehen, hängt davon ab, wo Sie sie verfolgen. Wenn Sie temporäre Preise oder Preise für Kundengruppen wünschen, können Sie dies auch hinzufügen.

Was Sie beschreiben, klingt jedoch nicht sehr unstrukturiert. Ich würde vorschlagen, mit einem minimalen Design zu beginnen und nach Bedarf zu erweitern, anstatt mit einem EAV-Design, und es später zu bereuen.

Chris Travers
quelle
9

Es gibt hier einige SQL Server-Besonderheiten, aber ich gebe meinen Überblick über EAV im Allgemeinen . Es ist nicht der Teufel, für den es oft gehalten wird, und einige der typischen Ausredenprobleme können vermieden werden. Zum Beispiel sagte @KookieMonster, dass Sie nicht erzwingen können, dass ein Benutzer keine zwei Geburtsdaten hat, aber das ist einfach:

CREATE TABLE dbo.Users
(
  UserID INT PRIMARY KEY,
  Username NVARCHAR(255) UNIQUE
  --, ...
);

CREATE TABLE dbo.Properties
(
  PropertyID INT PRIMARY KEY,
  Name SYSNAME UNIQUE
  --, ...
);

CREATE TABLE dbo.UserProperties
(
  UserID INT FOREIGN KEY ...,
  PropertyID INT FOREIGN KEY ...,
  DateValue DATE,
  IntValue INT,
  -- ...
  PRIMARY KEY(UserID, PropertyID)
);

(Auch dies ist die SQL Server-Syntax, aber hoffentlich stimmt das Konzept überein.)

Wenn die Logik komplexer ist (z. B. können sie drei Telefonnummern, aber nur ein Geburtsdatum haben), wird sie etwas komplizierter, aber Sie können dennoch Dinge, die Ihrer Geschäftslogik entsprechen, mithilfe von Triggern, gespeicherten Prozeduren usw. durchsetzen Ich weiß nicht, wie eine andere Lösung dieses Problem besser lösen kann, ohne gleichzeitig andere vorzustellen.

Die Leistung kann ein Problem sein, wir haben dies jedoch in SQL Server 2008+ mithilfe gefilterter Indizes (für bestimmte Eigenschaften) und verzögerter Materialisierung denormalisierter Versionen der Tabellen gelöst. Für Eigenschaftensätze, die sich langsam ändern, ist es einfach, Hintergrundprozesse zu erstellen, die die Tabellen reduzieren, sodass Sie für bestimmte oder alle Produkte eine materialisierte, schwenkbare Version der Daten haben, um alle Verknüpfungen zu vermeiden. Wie das in MySQL funktionieren würde, weiß ich nicht genau, daher werde ich keine Syntax bereitstellen, aber vielleicht werde ich aus der SQL Server-Perspektive weiter darüber bloggen ...

Aaron Bertrand
quelle
1
+1 für das Zeigen der guten Seiten von EAV auch. Es ist sicherlich ein überschaubares Modell, aber wie Sie bemerkt haben, kann die Durchsetzung der Logik schwierig werden (z. B. ein Geburtsdatum und drei Telefonnummern). Wer sich für diesen Weg entscheidet, sollte die Nachteile kennen ... und die Vorteile!
KookieMonster
@KookieMonster also der andere Weg wäre, was? Drei Spalten mit Telefonnummern und eine Spalte mit Geburtsdatum? Und wenn Sie eine 4. Telefonnummer hinzufügen möchten, müssen Sie eine neue Spalte hinzufügen? Wie gesagt, die Durchsetzung bestimmter Regeln kann komplex sein, aber ich übernehme diese normalerweise für ein sich ständig änderndes Schema, eine sich ständig anpassende API und eine immer größer werdende Tabelle.
Aaron Bertrand
+1 wie @KookieMonster sagte. Die große Sache ist, IMO, EAV ist für einige Dinge wirklich großartig . Wir verwenden es zum Beispiel in einigen Bereichen des LedgerSMB-Codes. Ich bin mir ziemlich sicher, dass es nicht der richtige Ort ist, um mit diesem Problem zu beginnen, aber es könnte ein wichtiger Teil der Lösung sein.
Chris Travers
Ich stimme voll und ganz zu.
KookieMonster
7

Verwenden Sie nicht MySQL, eine relationale Datenbank wird nicht zur Lösung dieser Art von Problem verwendet. Verwenden Sie ein Dokument oder eine NoSQL-Datenbank wie MongoDB oder möglicherweise RavenDB unter Windows.

Oder verwenden Sie alternativ PostgreSQL. Wenn Sie einen Basissatz von Attributen haben, können Sie Vererbung in Ihre Tabellen einbauen

create table base_items
( id bigint,
title varchar(50),
price money)

dann für die anderen Gegenstände sagen Bücher oder Essen

create table book_items 
(isbn varchar(20))
inherits (base_items)

create table food_items (date expiry_date)
inherits(base_items)

Machen Sie Ihre Daten

insert into base_items (id,item,amount) values
(3,'soap',0.99);

insert into food_items (id,item,expiry,amount) values
(4,'banana','2012-01-01',0.50);

insert into book_items (id,item,isbn,amount) values
(1,'some book','ABC-000-02100',20.99);

insert into book_items (id,item,isbn,amount) values
(2,'some other book','ABC-000-02102',20.99);

und

select * from base_items;
 id |      item       | amount
----+-----------------+--------
  3 | soap            |  £0.99
  1 | some book       | £20.99
  2 | some other book | £20.99
  4 | banana          |  £0.50


 select * from book_items;
 id |      item       | amount |     isbn
----+-----------------+--------+---------------
  1 | some book       | £20.99 | ABC-000-02100
  2 | some other book | £20.99 | ABC-000-02102


select * from food_items;
 id |  item  | amount |   expiry
----+--------+--------+------------
  4 | banana |  £0.50 | 2012-01-01
Paddy Carroll
quelle
5
Wirf hier nicht einfach einen solchen Satz. Solche Sätze werden nicht verwendet, um diese Art von Frage zu beantworten, sondern um etwas zu verkaufen. Verwenden Sie die Erklärung zu DBA.SE.
Dekso
4
@PaddyCarroll Obwohl ich in der Essenz der Antwort nicht einverstanden bin, habe ich mich nicht dafür entschieden. Ich habe abgelehnt, weil Ihre Antwort zu kurz ist. Schauen Sie, sogar Ihre Kommentarantwort auf Chris ist länger als Ihre Antwort. Bitte geben Sie dies (und jede andere Begründung, die Sie haben) für Ihre Antwort an, und ich werde gerne meine Stimme umkehren. Ich glaube nicht, dass sich jemand auf dieser Seite gegen andere Ansichten ausspricht, aber wir lehnen weniger erklärte und begründete Antworten ab.
Ypercubeᵀᴹ
3
Sie mögen Recht haben, aber damit ich das anerkenne, fehlen ein paar Punkte: Warum NoSQL, was sind die Vorteile gegenüber EAV, Supertyp-Subtyp, Chris 'Vorschlag oder anderen möglichen Lösungen (spärliche Tabellen usw.)
dezso
4
@PaddyCarroll Bitte fügen Sie dieser Antwort etwas mehr Substanz hinzu, oder ich betrachte es als Kommentar und konvertiere es für Sie. "Mach das nicht" ist keine Antwort, es sei denn, es enthält auch ein "Mach das stattdessen" und du erklärst nichts darüber, warum er eine Implementierung einer anderen vorziehen sollte.
JNK
1
Großartige Bearbeitung. Sehr informativ. Eine Kleinigkeit, die ich hinzufügen möchte, ist, dass die Tabellenvererbung in PostgreSQL voller obskurer Fallstricke ist. Es kann wichtige Probleme lösen (und kann hier durchaus Teil einer Lösung sein), aber es funktioniert nicht immer so, wie es die Leute erwarten. Verwenden Sie es mit Vorsicht. (Mein Blog, ledgersmbdev.blogspot.com , hat eine ganze Reihe von Beiträgen zu solchen Dingen)
Chris Travers
6

Wenn diese Datenbank in irgendeiner Weise mit dem verbunden ist, was Ihre Verbraucher kaufen, wird die Leistung bald eines Ihrer wichtigsten Probleme sein. Ich sage nicht, dass EAV keinen Platz in der Datenbankwelt hat, aber Sie werden mit diesem Modell wahrscheinlich mehr Probleme als Antworten bringen. Da ich eine solche Datenbank (von Drittanbietern) selbst verwalten muss, sind folgende Punkte zu beachten:

  • Die Leistung kann ziemlich schnell schlecht werden: Wenn Sie alle Felder für ein bestimmtes Produkt, einen bestimmten Kunden, abrufen möchten, müssen Sie die LEFT JOINs multiplizieren, da jedes Attribut in einer anderen Zeile gespeichert wird. Stellen Sie sich nun vor, Sie hätten Hunderte von Feldern zum Verbinden.

  • Datenintegrität: Es wird schwierig sein, sie durchzusetzen. Zum Beispiel hindert niemand den Kunden daran, zwei (oder mehr) Geburtsdaten zu haben. Wenn isbn für Bücher erforderlich ist, wie stellen Sie sicher, dass dies der Fall ist? Was ist der Feldtyp Ihres Geburtstagsfeldes? Sie können eine Menge Code haben, der Ihnen dabei hilft, aber das Schreiben ist schwierig und langwierig und wirkt sich sicherlich auf die Leistung aus.

Die Liste kann weitergehen, und meine Lieblingslesung zu diesem Thema ist Pragmatic SQL Antipatterns von Bill Karwin. Sie können sich auch dieses Video, SQL Best Practices, in weniger als 20 Minuten ansehen . Unser Anbieter kann seine Architektur jetzt nicht ändern (würde monatelange Neugestaltung erfordern) und es häufen sich Probleme für unser Datenvolumen. Wägen Sie die Vor- und Nachteile sorgfältig ab, bevor Sie diesen Weg gehen.

KookieMonster
quelle
EAV funktioniert sehr gut für einige sehr spezifische Datentypen, bei denen die Daten tatsächlich mit einem EAV-Modell übereinstimmen. Zum Beispiel Parameter für eine HTTP-Anfrage ..... Obwohl ich nicht bereit bin, sie kategorisch als Antimuster zu bezeichnen, stimme ich dem vollkommen zu.
Chris Travers