# mit Multi-Thread Daten aus Datenbank lesen und schreiben



## ottens (4. Nov 2015)

Hallo Leute,
ich versuche mit ExecuterService (n) Threads [Gruppe-A] zu starten 5-10 (auf dem Server können mehr als 10 sein). Ein Thread der [Gruppe-A] bekommt einen Job zu erledigen, ein Thread startet noch 4 Threads [Gruppe-B] auch von einem anderen ExecuterServic, pro Thread der [Gruppe-B] liest Daten und vergleicht sie ob sie in Daten-Tabelle existiert, wenn ja wird die ID zurückgeliefert (FK) sonst wird der Eintrag geschrieben und sein ID zurückgeliefert (also Entfernung von Duplikaten) Hier brauche ich synchronization besonders wenn Daten geschrieben werden gibt es eine Möglichkeit um das Ziel zu erreichen, dass die Daten korrekt geschrieben werden, hier möchte ich *Phantom-Read* vermeiden.
*Phantom-Read* bedeuted, daß keine 2 Threads versuchen eine bestimmte ID zu lesen, stellen sie beide fest sie existiret nicht und versuchen jetzt beide diese ID zu schreiben, weil sie UNIQUE sein soll.
habe mit synchronized, Monitor und Lock versucht hilft aber nicht, glaube weil mehrere Threads im Spiel sind.
für eine Idee, Antwort, Vorschlag oder Lösung wie die Implementierung realisiret wird, bedanke ich mich.

Grüße Ottens


----------



## Joose (4. Nov 2015)

(Ich hoffe ich habe das Problem richtig verstanden)

Du könntest am Anfang 1x alle IDs lesen und in eine Thread-safe Liste (am besten nach FIFO-Prinzip) legen. Jeder Thread nimmt sich dann immer die nächste ID aus der Liste.
Kommen zur Laufzeit neue IDs hinzu handelt es sich um ein Producer/Consumer Problem. Dann muss der Thread (Producer) der die ID ausliest eben immer wieder lesen und die Liste ergänzen. Die anderen nehmen sich immer wieder eine ID raus (Consumer) und verarbeiten diese.


----------



## Thallius (4. Nov 2015)

Du must doch lediglich um das Testen ob es die ID schon gibt und das dann eventuelle Neuschreiben eine DB Transction legen.


----------



## ottens (4. Nov 2015)

danke für die Antwort also am Anfanf der Main-Thread liest die Daten und zersütcklet sie in Jobs
(pro JOB z.B 1000 Schritt) die ID's werden zur Laufzeit nicht verändert also kommen keine neue ID's
hinzu schon mal die gute Nachricht. dann mit for-Schleife bekommt einen Thread [Gruppe-A] einen JOB
pro JOB startet noch 4 Threads [Gruppe-B] auch vom Typ ExecuterService wie beschrieben
möchte die Application beschleunigen, weil Millionen von Einträgen existieren, das Problem ist
*Phatom-Read *und möchte die Daten richtig in den Tabellen geschrieben werden sonst bekomme ich inkonsistenze Daten.
also weiß jemand ob mit synchronize oder Monitor prinzip werden nur zwei Thread synchronisiret oder mehrere wie ich weiß werden mehrere aber das tut bei mir nicht glaube habe Dankfehler ?

danke euch


----------



## Thallius (4. Nov 2015)

Dein Denkfehler ist alleine schon Threads zu benutzen damit es schneller wird sie dann aber wieder synchronisieren zu wollen. Das bringt doch nichts.


----------



## ottens (4. Nov 2015)

ja ok gibt es einen besseren Vorschlag ? also ich hatte die selbe Applikation aber der Import dauert 60 Tage wenn man keine Threads benutzt !!


----------



## Joose (4. Nov 2015)

Ich verstehe den Sinn hinter diesen beiden Thread Gruppen nicht. Warum kannst du nicht mehr Thread von A erzeugen und ersparst dir die Thread von B?

Alternative: Trage die zu schreibende Daten in eine Liste (threadsafe) ein. Ein seperater Thread kümmert sich darum diese in die DB zu schreiben. Natürlich muss sich dieser Thread merken welche er schon geschrieben hat damit nichts doppelt geschrieben wird.

EDIT: Natürlich können das schreiben der Daten auch X Threads übernehmen.
Hier würde es sich um eben wieder um ein Producer/Consumer Pattern handeln.

Die einen Threads sagen welche Daten geschrieben werden sollen. Durch die Threadsafe Liste wird das ganze synchronisiert und die X Threads konsumieren die zuschreibenden Daten und fügen sie in die DB ein. (In diesem Fall muss man vorher immer überprüfen ob die Daten schon von einem anderen Thread in die DB geschrieben wurden)


----------



## ottens (4. Nov 2015)

ok die zweite Gruppe vo Threads [Gruppe-B] sollte die Grupp-A entlasten also die Arbeit auf mehrere Worker verteilen also Stufen von Threads.
danke versuche mit einer Gruppe von Threads die ganze Arbeit zu erledigen d.h  vergleichen falls nötig schreiben. danke


----------



## Thallius (4. Nov 2015)

Hast du denn überhaupt mal genau nachgeforscht WAS so langsam ist? Ich glaube nicht das das an der geringen CPU Auslastung deines Rechners liegt. Das Nadelöhr ist bestimmt ganz wo anders und das rettest du mit multi-thresdding dann ja auch nicht.


----------



## ottens (4. Nov 2015)

Hallo danke für die Antwort.
ich glaube die Frage bezieht sich auf die alte Application, sie hat die Aufgabe lese DB_1 vergleiche den gelesenen Eintrag in DB_2 falls existiert liefere seinen Id sonst importieren und LAST_Inserted_ID lesen
die ID wird in DB_2 gespeichert das Problem beim Lesen wie auch Schreiben gibt eine Tabelle die sehr lang wird also wächst ich glaube sie verursacht, daß die Applicaton langsam wird,obwohl dort wurde Index gesetzt. die Daten sind jetzt mehr geworden und soll die Application beschleunigt werden.
dazu sollen die Daten schneller und dichetr gelsene werden, damit die Verarbeitung schneller wird ich meine es soll keinen Thread warten bis die Daten ankommen, damit er sie verarbeitet bzw die Daten sollen warten bis sie dran sind.
bedanke mich ganz herzlich für nette Vorschläge.


----------



## Joose (4. Nov 2015)

Das beantwortet nicht wirklich die Frage von Thallius. Das ist nur deine/eure Vermutung.
Habt ihr schon mittels Profiler und ähnlichen kontrolliert wo das Programm lange braucht? Möglicherweise kann man am aktuellen Code an ein paar wenigen Stellen etwas anpassen aber dadurch einiges an Performance rausholen.


----------



## ottens (4. Nov 2015)

Hallo das Programm lief gut ohne problem bis die Menge der Daten sich explosionsartig gewachsen ist
daher wollen wir mit Multi-Threading es beschleunigen.
Gibt es eine grobe Einschätzung wieviele Daten (Durchschnitt) sollen pro Stunde oder pro Tag verarbeitet werden sollen oder kann man nicht sagen ?

Grüße


----------



## Joose (4. Nov 2015)

ottens hat gesagt.:


> Hallo das Programm lief gut ohne problem bis die Menge der Daten sich explosionsartig gewachsen ist



Trotzdem könnte es sein das eurer jetztiges Programm es ohne Probleme schaffen könnte wenn man nur ein paar Stellen anpasst. 
Bevor ihr wirklich etwas komplett neues programmiert, kontrolliert doch einfach ob die bisherige Lösung nicht doch weiter verwendet werden kann. Dazu einfach mal mittels Profiler kontrollieren wo die Zeit liegen bleibt.

Wenn die Zeit auf der DB liegen bleibt dann hilft ein neues Programm nichts, da es die Datenbank nicht beeinflusst.



ottens hat gesagt.:


> daher wollen wir mit Multi-Threading es beschleunigen.



Multithreaded bedeutet aber nicht immer schneller 



ottens hat gesagt.:


> Gibt es eine grobe Einschätzung wieviele Daten (Durchschnitt) sollen pro Stunde oder pro Tag verarbeitet werden sollen oder kann man nicht sagen ?



Was erwartest du dir auf so eine Frage als Antwort? Wieviel Daten dein Programm bzw. deine Datenbank pro Std oder pro Tag verarbeiten kann hängt von vielen Faktoren ab (Hardware, Konfiguration der DB, dein Programm, Netzwerkverbindung - Geschwindigkeit, ....


----------



## Thallius (4. Nov 2015)

Von welchen Größenordnungen reden wir denn hier? Alleine schon das umkopieren von Tabellen erscheint mir wenig sinnvoll. Wozu soll es gut sein Datensätze die in einer Tabelle drin sind, in eine andere nochmal reinzuschreiben? Da kann man sie auch genausogut aus der ersten lesen?


----------



## Joose (4. Nov 2015)

Thallius hat gesagt.:


> Alleine schon das umkopieren von Tabellen erscheint mir wenig sinnvoll.



Naja wenn ich es richtig verstanden habe nehmen sie Datensätze aus Datenbank A ,vergleichen sie mit was aus Datenbank B und wenn in Datenbank B nichts vorhanden ist tragen sie dort Daten ein.
Was aber nur die Fragestellung ändern würde. Warum werden die Daten nicht gleich verglichen und dann auf Datenbank B gespeichert.


----------



## ottens (4. Nov 2015)

Hallo was meinst du mit wenn die Zeit liegen bleibt ? 
ja das stimmt manchmal die Verwaltung von Multi-Threads kostet mehr Zeit als weniger einzelne Threads 
das ist schon mir klar aber die Hardware hält noch mehr also kann mehr anbieten Zahl der CPU 
sowohl auch RAM-Größe. 
die Applikation soll viele ID's sammeln um einen Schritt zu schaffen es sind viele Tabellen dabei beteiligt daher braucht viel Zeit und man möchte nicht watern wann die Daten da sind, sondern soll man die Daten holen und sie in Queue stellen.

ich benutze jvisualvm, und mit Workbench kann man sehen wie der Server sich langweilt und die Prozesse des Servers top-Befehl kann man auch sehen es gibt noch Potential nach oben.

ich dachte gibt so einen Richtwert, mit dem man sich orientieren kann ob die Applikation schnell genug oder nicht ?
Grüße


----------



## ottens (4. Nov 2015)

Hallo Joose,

alle sind Rohdaten, sie werden in mehreren Schritten gefiltert, damit man sie (die Daten) vorbereiten d.h die Daten werden geputzt und standardisiert erst und auf gleichen Nenner gebracht werden hier hat man damit DB_1 erstellt, dann
wird von DB_1 gelesen und mit DB_2 verglichen falls die Aktuell verglichehen Daten in DB_2 existieren dann wird die ID geholt falls nicht existieren dann werden sie in DB_2 geschrieben und ihre ID geholt die se ID wird in FAKT-Tabelle geschrieben als FK dierer Vorgang wird ofter stattfinden z.B Auto hat Reifen, Elektronik usw hier soll man die Reifen_Hersteller_ID lesen sowohl auch Elekrtonik_Hersteller_ID holen und in Zentralle Tabelle geschrieben usw.

Grüße,


----------



## Thallius (4. Nov 2015)

Mir scheint da wird eine Datenbank mal wieder nur als Datenspeicher verwendet. Das das langsam ist ist vollkommen normal...


----------



## Joose (4. Nov 2015)

ottens hat gesagt.:


> Hallo was meinst du mit wenn die Zeit liegen bleibt



Beispiel mit irgendwelchen Zahlen:
Deine Applikation braucht um 100.000 Datensätze zu verarbeiten gesamt 10 Minuten.
Davon arbeitet die Datenbank 9 Minuten lang und dein Programm nur 1 Minute (wirkliche Prozessorzeit).
Dann lässt du bei der DB 90% der Zeit liegen. Da würde es nur gerinfügig helfen dein Programm von der Performance her zu verbessern. So kannst du zwar die 1 Minute noch verbessern. Aber die 9 Minuten auf der DB werden nur gerinfügig besser.

Sprich braucht wirklich die Applikation solange um die Daten zu verarbeiten oder braucht die DB solange um die Befehle abzuarbeiten? (-> wo bleibt die Zeit liegen)



ottens hat gesagt.:


> das ist schon mir klar aber die Hardware hält noch mehr also kann mehr anbieten Zahl der CPU
> sowohl auch RAM-Größe.



Was auch immer du damit sagen willst, ich weiß es nicht. Ganze Sätze wären hierbei hilfreich.



ottens hat gesagt.:


> ich dachte gibt so einen Richtwert, mit dem man sich orientieren kann ob die Applikation schnell genug oder nicht ?



Nein das hängt ganz davon ab was für eine Applikation das ist.
Bildbearbeitungsprogramme dürfen schon mal mehr Speicher und CPU verbrauchen da werden komplexe Berechnung durchgeführt. Mathematische Programme können ebenfalls viel CPU brauchen. Eine simple Userverwaltung für einen Verein sollte nicht wirklich Ressourcen verbrauchen. 



ottens hat gesagt.:


> alle sind Rohdaten, sie werden in mehreren Schritten gefiltert, damit man sie (die Daten) vorbereiten d.h die Daten werden geputzt und standardisiert erst und auf gleichen Nenner gebracht werden hier hat man damit DB_1 erstellt, dann
> wird von DB_1 gelesen und mit DB_2 verglichen ..............



Warum werden die Daten nicht gleich mit DB2 abgeglichen? Das erspart die ganzen Schreib und Leseoperation von DB1


----------



## ottens (4. Nov 2015)

Hallo Thallius,
man kann so sagen die Daten werden aber von bestimmten Usern benutzt, ausgewertet und analysiert
anhand dessen kann man auch Artikel bestellen (aber keine Daten über Personen).   

Grüße,


----------



## ottens (4. Nov 2015)

Hallo Joose,

also die Rohdaten existieren eigentlich als zig Files, die eine Applikation liest und in die DB importiert sie in die einzelne Tabellen, die zweite Applikation soll die Filterung erledigen bis jetzt war der Ablauf so jetzt die Software API    www.chemaxon.com    wird aktuallisiert dazu unsere Anforderung werden immer angepasst.

man muß das Problem zerlegen , z.b man kann nicht die ganze Applikation in einer Klasse packen oder
sieht ihr das anders ? man soll die Schwierigkeiten Schritt für Schritt lösen.


----------



## Joose (4. Nov 2015)

ottens hat gesagt.:


> man muß das Problem zerlegen , z.b man kann nicht die ganze Applikation in einer Klasse packen oder
> sieht ihr das anders ? man soll die Schwierigkeiten Schritt für Schritt lösen.



Klar kann man wahrscheinlich alles in eine Klasse bleiben, aber es wird dann keiner mehr durchblicken können wo was passiert 
Und das man das Problem auf einzelne Teile zerlegt ist auch vollkommen in Ordnung.
Schritt für Schritt heißt nur das man nicht an allen Ecken eines Programmes gleichzeitig entwickeln sollte 

Aber zu deinem Problem haben wir dir schon Lösungen genannt bzw. auch Ansätze zu überprüfen wo denn genau das Problem liegt.


----------



## ottens (4. Nov 2015)

danke euch viel als Ansatz habe auch einen SQL-Befehl INSERT IGNORE es kann auch helfen falls duplikate 
vemieden werden sollen, weil die Applikation duplikate nicht importieren soll, weil sie UNIQUE bleiben müßen.

beste Grüße,


----------

