Mysql Redundante Daten vermeiden

Hallo,

ich möchte eine DB aufbauen, da ich derzeit alles im RAM speichere. Möchte die Daten aber persistent halten, da es unnützer Aufwand ist alles immer wieder zu lesen. Folgendes Szenario:

Ich lade ca 15 CSV Dateien mit Artikeldaten. Wir haben 30 Shops in welche diese Daten abgeglichen werden müssen (Preise, Bestände etc) dabei werden noch die Preise kalkuliert etc.

Nun möchte ich die CSV einlesen und für jeden Shop den passenden Preis speichern und den Bestand sowie Artikelbeschreibungen etc.

Beim nächsten Einlesen (alle 2h) soll dann nur noch abgeglichen werden, welche Artikeldaten sich wirklich geändert haben. Wenn sich ein Artikel geändert hat, soll dieser auch in den entsprechenden Shops aktualisiert werden.

Wie würdet ihr das machen? Ich nutze Java und MySQL

Datenbank würde ich so aufbauen:

Tabelle artikel

  • id (PK)
    -name
    -beschreibung
    -kurzBeschreibung
    -einkaufsPreis
    -änderung

Tabelle shoppreise
-id (PK)
-preisShop1
-preisShop2
usw

Beim einlesen wird Spalte Änderung auf 0 gesetzt und sobald eine Änderung festgestellt wurde, wird dies mit “1” signalisiert. Nach dem Einlesen aller CSV Daten, wird gepüft welcher Artikel Änderungen hat und wird im passenden Shop aktualisiert.

Freue mich auf Verbesserungsvorschläge

Mir sind noch ein paar Sachen unklar:

Ändern sich denn nur die Shoppreise? Weil du sagtest, dass auch Bestände etc. abgeglichen werden?
Was ist, wenn sich der Preis in zwei Shops unterschiedlich ändert, oder beziehst du den “richtigen” Preis von einer anderen Quelle bzw. der Kalkulation aus den entgegengenommenen Daten?

Würde sonst für die Artikel eine Tabelle machen, eine für die verschiedenen Shops und dann eine Tabelle, die jeweils die erweiterten Daten für die Artikel (Preis, Bestand, Änderung) mit dem Artikel(ID) und dem Shop (ID) verknüpfen.

preisShop1, preisShop2 sieht schon sehr verdächtig aus. Normalerweise würde man eine Tabelle mit Artikeln, eine Tabelle mit den Shops, und eine “Zwischentabelle” mit den Artikelpreisen im jeweiligen Shop haben. Strukturell etwa so (nur mit einer zusätzlichen Spalte für die Preise):

http://www.inf-schule.de/content/information/datenbanksysteme/ermodelle/datenmodell/beziehungstyp_nm.png

Ok, dann hab ich aber in der Zwischentabelle mit den Preisen ca weit über Millionen Einträge?! (Jeder Shop kann bis zu 100.000 Artikel haben)

Das ist erstmal nicht schlimm. Falls es sich später herausstellen sollte, dass das ein Performanceproblem darstellt, dann kann man die Tabelle immer noch denormalisieren.
Diese Denormalisierung ist aber wirklich ungünstig, weil eine Änderung der Shopanzahl eine Schemaänderung zur Folge hat.

Ok, danke! Es werden immer mehr Shops dazu kommen, wäre natürlich doof da jedes mal ne Tabelle erzeugen zu müssen.

Die Tabellen erzeugst du doch per Einlesen der CSVs. Daher muss dieser Mechanismus in der von Landei vorgeschlagenen Struktur vorhandene Shops und Artikel aktualisieren unn neue Shops und Artikel selbstständig einpflegen. Sinnigerweise sollte der Dateiname der jeweiligen CSV dazu als ShopID dienen oder zumindest eine eindeutige ID in der jeweiligen CSV auftauchen. Bei einer neuen ID wird dann schlicht ein neuer Shop (Datensatz im Shop-Table) angelegt. Bei neuen Artikeln werden diese zunächst im Artikel-Table angelegt und dann wird auch gleich der Referenztable für diesen aktualisiert.

Sucht man im Referenztabelle dann nach Shops, erhält man eine Liste mit Preisen für dessen Artikel. Sucht man hingegen nach Artikeln erhält man eine Liste mit Shops und die Preise, für die sie dort angeboten werden.

Die Tabellen erzeug ich nicht mit dem einlesen. Mit dem Einlesen werden Artikel angelegt und updated.

und so:

Tabelle shop

  • id PK
    -shopname

Tabelle großhandel(welcher Shop hat welchen großhandel, ist festgelegt)
-id
-grosshandelname

tabelle artikel
-id
-name
-ekPreis
etc

tabelle preise
-id
-artikelID
-shopID
-preis

Wäre das so ok?

Für Zwischentabellen braucht man keine eigene ID, da kann man artikelID und shopID als compound key verwenden (die Kombination der beiden muss ja sowieso unique sein).

Ja, schon klar. Nur vergisst du dabei zwei weitere Tabellen, die geupdatet werden müssen:

  1. Die Tabelle der verwalteten Shops und
  2. Die Tabelle der Artikel-Shop-Preis-Referenzen.

Für jede aktuell eingelesene CSV also:

  1. Im Shop-Table nachsehen, ob jemals schon eine CSV dieses Shops eingelesen wurde.
    1a) ist dies nicht der Fall, Shopdatensatz erstellen.
  2. Einlesen der Artikel
    2a) Ist der Artikel im Artikel-Table noch nicht vorhanden, dort anlegen.
    2b) In jedem Fall den Referenz-Table (bei Landei der Mittlere) aktualisieren.

So funktionieren üblicherweise grob Preisroboter von Shopping-Platformen (Amazon z.B.), jedoch nicht zwangsläufig mit CSVs.

Bei dem was du da machen willst, wäre eine Zentrale Artikel- und Shopverwaltung gut. Also eine, bei welcher Warenbestand und Preise in den Shops zentral verwaltet werden. Dann werden nämlich die Datenbanken in den einzelnen Shops vollkommen überflüssig.

Ja wäre sinnvoll geht aber nicht. Da die Shops mit unter nicht unsere sind, sondern die Betreiber die Artikeldaten von uns aufarbeiten lassen.

Wie würde dein DB Modell aussehen?

Vielleicht sollte ich auch eine Art Microservices machen:

Über Timer EJB läuft Service A und prüft, welche Shops Daten von Großhandel A bekommen, dann wird die CSV vom Hersteller geholt , die Daten vom Shop werden geholt (wie viel Aufschlag, etc) dann werden die Shops updated. Dann gehts weiter mit Großhandel B, usw

Bin mir grad nicht sicher wie ich den Ablauf programmieren soll

Also mein zentraler Service sähe so aus, dass ich für die Artikel neben den Dingen die klar sind, mindestens einen Bestand und einen festen EK habe. Für die Shops dann noch einen produktabhängigen regional bedingten Faktor für dort gängige Verkaufspreise. Großhändler wären mir dabei egal, zumal ja die Shopverwaltung mir obliegt, wenn es meine Shops wären.

Da es sich aber nicht um deine Shops handelt, fällt das wohl aus. Mir stellen sich nun aber weitere Fragen. Ganz oben: Was willst du überhaupt erreichen? Jeder Händler hat eine individuelle Preisgestaltung, individuelle Großhändler, bei denen sie abhängig von abgenommenen Mengen individuelle Rabatte bekommen und individuelle Gewinnvorstellungen, die auch damit zusammenhängen, ob man stets der günstigste sein will oder nur am Markt bestehen will. Da lässt sich eigentlich nichts zentral optimieren. Du kannst den Shopinhabern lediglich Preisvorschläge machen, z.B. die Preise, die der günstigste von den von dir verwalteten Shops nimmt. Ist dieser Preis für einen Inhaber bereits zu hoch, weil er schon im Einkauf mehr bezahlt hat, lässt sich dieser Preis für diesen Shopinhaber nicht mehr optimieren. Wenn man bedenkt, dass es Großhändlerkunden gibt, die Aufgrund der Stückzahlen, die sie von einem Artikel bestellen oder aus Treuegründen bereits 50% Rabatt bekommen, kann dieses von einem, der nur 20% bekommt, sicher nicht mehr getoppt werden - der mit den 50% ist ja selbst dann noch über den 20%, wenn er noch Mehrwertsteuer und Gewinnspanne draufrechnet. Was willst du da wie optimieren?

Aktuell habe ich es so programmiert, dass jeder fremde Shop im System seine individuelle CSv hinterlegt vom Großhandel(mit seinen speziellen ek Preisen). Weiterhin hat er die Möglichkeit in einer Maske die Aufschläge individuell zu erfassen.

Beim Start lädt das Programm die individuelle csv und Geht das Programm diese Artikel für artikel durch und berechnet anhand der Aufschläge seine vk Preise.

Nun werden aber teilweise 20 mal die selben datein geladen (20 fremde Shops nutzen den gleiche Großhandel ohne individuelle Preise). Das ist aber völlige Last alles doppelt und dreifach zu verarbeiten für ein und die selben Daten.

Die Fremden Shops können mir die csv ihres Großhandels senden und ich binde diese dann individuell an, wenn möglich.

Diese ganzen Daten möchte ich aber nun zentral speichern, damit das mehrfache einlesen aufhört. Daher will ich lieber die individuellen Preise speichern. Aber mir fällt grad was ein… ich könnte ja die Preise während der Laufzeit berechnen. Sprich das Programm schaut in der db welche Artikel Änderungen aufweisen, holt sich den Aufschlag für das Produkt und berechnet vor dem shopupdate den Preis. So muss ich die Preise nicht speichern, sondern nur die Faktoren und weitere Aufschläge. Das wäre doch was oder :slight_smile: