• Hallo liebe Userinnen und User,

    nach bereits längeren Planungen und Vorbereitungen sind wir nun von vBulletin auf Xenforo umgestiegen. Die Umstellung musste leider aufgrund der Serverprobleme der letzten Tage notgedrungen vorverlegt werden. Das neue Forum ist soweit voll funktionsfähig, allerdings sind noch nicht alle der gewohnten Funktionen vorhanden. Nach Möglichkeit werden wir sie in den nächsten Wochen nachrüsten. Dafür sollte es nun einige der Probleme lösen, die wir in den letzten Tagen, Wochen und Monaten hatten. Auch der Server ist nun potenter als bei unserem alten Hoster, wodurch wir nun langfristig den Tank mit Bytes vollgetankt haben.

    Anfangs mag die neue Boardsoftware etwas ungewohnt sein, aber man findet sich recht schnell ein. Wir wissen, dass ihr alle Gewohnheitstiere seid, aber gebt dem neuen Board eine Chance.
    Sollte etwas der neuen oder auch gewohnten Funktionen unklar sein, könnt ihr den "Wo issn da der Button zu"-Thread im Feedback nutzen. Bugs meldet ihr bitte im Bugtracker, es wird sicher welche geben die uns noch nicht aufgefallen sind. Ich werde das dann versuchen, halbwegs im Startbeitrag übersichtlich zu halten, was an Arbeit noch aussteht.

    Neu ist, dass die Boardsoftware deutlich besser für Mobiltelefone und diverse Endgeräte geeignet ist und nun auch im mobilen Style alle Funktionen verfügbar sind. Am Desktop findet ihr oben rechts sowohl den Umschalter zwischen hellem und dunklem Style. Am Handy ist der Hell-/Dunkelschalter am Ende der Seite. Damit sollte zukünftig jeder sein Board so konfigurieren können, wie es ihm am liebsten ist.


    Die restlichen Funktionen sollten eigentlich soweit wie gewohnt funktionieren. Einfach mal ein wenig damit spielen oder bei Unklarheiten im Thread nachfragen. Viel Spaß im ngb 2.0.

[Java] Skalierbarkeit von 1:1 Kopie von einer Datenbank

Larius

OutOfOrder

Registriert
12 Juli 2013
Beiträge
5.792
Hallo alle zusammen,

mir spukt schon seit längerem eine Idee durch den Kopf, die aber noch ein paar Macken hat. Es geht hierbei um die 1:1 Kopie (alle Tabellen, Constraints und Datensätze) von einer in eine andere Datenbank. Hierbei ist soll es jedoch keine Rolle spielen welche Datenbanksysteme im Hintergrund laufen, sondern es geht rein um die Performance der Operation, da eine Datenbank mit beliebiger Größe in angemessener Zeit (also keine Dauer mehreren Wochen für eine einfache Kopie) kopiert werden soll.

Ich habe mir überlegt das ich pro Tabelle zumindest 1 Thread abstelle bzw. einen Threadpool inder Größe der Anzahl der Tabellen anlege. Dies hätte den Vorteil das kleinere Tabellen, welche fertig abgearbeitet worden sind, keine Systemressourcen blockieren bzw. der Thread in einer anderen Tabelle die Datensätze abarbeiten kann. Jetzt stellt sich nur eine Frage: Schafft überhaupt eine Datenbank, soviele Requests gleichzeitig abzuarbeiten? Da ich nämlich auch vorhabe für jeden Datensatz eine Checksumme anzulegen, um sicher zu stellen das die DB auch danach in dem richtigen Zustand ist, würde also nicht 1 Datensatz, sondern 2 in die neue DB kopiert werden.

Übersehe ich da irgendwas oder werde ich mit dem Verfahren meine Datenbank komplett plätten?
 

Schinni999

Eat, Sleep, Code

Registriert
15 Juli 2013
Beiträge
404
Ort
Vor meinen Source Code
Ich glaube da sollte nicht viel passieren, aber ich kann mich von meinen Erfahrungen her nur auf SQL beziehen. Eine SQL Datenbank kann ca. 105.000 queries pro Sekunde verarbeiten. Ein Task nimmt deinen Request auf und wird von einem "Worker" verarbeitet ( Ein Worker ist fast sowas wie ein Thread ). Wie viele solcher Tasks/Worker erzeugt werden können hängt von der CPU-Leistung des Servers ab z.B:

Bei 16 Prozessoren -> 352 (32-Bit), 704 (64-Bit)
Bei 32 Prozessoren -> 480 (32-Bit), 960 (64-Bit)

Ich hoffe ich konnte dir ein bisschen helfen.
 

accC

gesperrt

Registriert
14 Juli 2013
Beiträge
5.250
Es lohnt sich eigentlich nur so viele Threads anzulegen, wie CPU-Kerne zur Verfügung stehen. Alles andere ist "überflüssig".
Tatsächlich gleichzeitig kann nämlich nur auf verschiedenen Kernen gearbeitet werden. Wenn du mehr Threads als Kerne hast (etwa 2 Threads / Kern), dann wechseln sich die Threads ab:
Thread 1 Schritt 1
Thread 2 Schritt 1
Thread 1 Schritt 2
Thread 2 Schritt 2
etc.

Natürlich nicht ganz so exakt, da macht das OS schon noch ein bisschen "Magie"..


@ Schinni999: Woher nimmst du die Zahl? "ca. 105.000 queries pro Sekunde" dürfte wohl auf eine ganz bestimmte Hardware und ganz bestimmte Komplexität der Querys zutreffen. Jetzt nur mal als unvollständiges Beispiel:
Eine einfache SELECT - Abfrage aus einer Tabelle dürfte weit weniger Resourcen in Anspruch nehmen, als etwa eine komplexe Anfrage mit vielen Joins, Crossjoins, etc.
Auch dürfte auf einem Oktacore Prozessor mit 5GHz je Kern, der mit SSD Festplatte ausgestattet ist oder mit einer entsprechenden RAM-Disc arbeitet, ein Query weniger Probleme bereiten, als etwa auf einem Pentium 1 mit 1MB RAM und einer 5200RPM Festplatte.
Konzepitionell sollten moderne Datenbanken eigentlich mit der Hardware skallieren.

Ohne mich genau mit dem multithreading von Datenbanken auszukennen, würde ich aus dem oben genannten Grund über die Anzahl der CPU-Kerne Threads erstellen. Zusätzlich hältst du eine Liste mit Tabellen (eventuell zusätzlich in Abschnitte geteilt) vor. Jeder Thread darf sich einen Abschnitt aus der Liste nehmen und den Abarbeiten, sobald ein Thread frei wird, nimmt er sich den nächsten Abschnitt aus der Liste.
 

Schinni999

Eat, Sleep, Code

Registriert
15 Juli 2013
Beiträge
404
Ort
Vor meinen Source Code
@ Schinni999: Woher nimmst du die Zahl? "ca. 105.000 queries pro Sekunde" dürfte wohl auf eine ganz bestimmte Hardware und ganz bestimmte Komplexität der Querys zutreffen. Jetzt nur mal als unvollständiges Beispiel:
Eine einfache SELECT - Abfrage aus einer Tabelle dürfte weit weniger Resourcen in Anspruch nehmen, als etwa eine komplexe Anfrage mit vielen Joins, Crossjoins, etc.
Auch dürfte auf einem Oktacore Prozessor mit 5GHz je Kern, der mit SSD Festplatte ausgestattet ist oder mit einer entsprechenden RAM-Disc arbeitet, ein Query weniger Probleme bereiten, als etwa auf einem Pentium 1 mit 1MB RAM und einer 5200RPM Festplatte.
Konzepitionell sollten moderne Datenbanken eigentlich mit der Hardware skallieren.

Ohne mich genau mit dem multithreading von Datenbanken auszukennen, würde ich aus dem oben genannten Grund über die Anzahl der CPU-Kerne Threads erstellen. Zusätzlich hältst du eine Liste mit Tabellen (eventuell zusätzlich in Abschnitte geteilt) vor. Jeder Thread darf sich einen Abschnitt aus der Liste nehmen und den Abarbeiten, sobald ein Thread frei wird, nimmt er sich den nächsten Abschnitt aus der Liste.

Diese Queries sind natürlich nur sehr einfache Selects. Diese 105.000 habe ich mal in einem anderen Forum zum Thema SQL gelesen. Diese Tabelle kommt von Microsoft zum SQL Server 2008 R2.
 

KaPiTN

♪♪♫ wild at heart ♪♫♫♪

Registriert
14 Juli 2013
Beiträge
29.138
Es lohnt sich eigentlich nur so viele Threads anzulegen, wie CPU-Kerne zur Verfügung stehen. Alles andere ist "überflüssig"..

Stellst Du gerade das Prinzip des Multithreading in Frage, welches es bereits bei Einkernsystemen gab? Natürlich gibt es hier Timesharing und keine wirklich parallele Verarbeitung.
Im Bereich der Dienst des MS SQL- Server werden afaik 5 Threads pro Kern unterstützt.
 

accC

gesperrt

Registriert
14 Juli 2013
Beiträge
5.250
Arg okay, hatte einen Denkfehler gemacht. Ja bitte streich einfach meine Aussage. Sorry.
 

Larius

OutOfOrder

Registriert
12 Juli 2013
Beiträge
5.792
  • Thread Starter Thread Starter
  • #7
Ich hab mich schon gewundert, dass es Time Sharing gibt, jo, logisch. Aber nur soviele Threads erzeugen wie CPU Kerne zur Verfügung stehen wäre mir neu gewesen. Vor allem wäre das bei einer größeren Datenmenge ein glatter Selbstmord gewesen.

Kapitn, das sind aber 5 Worker-Threads pro Core die die Requests verarbeiten, richtig? Nachdem das einfache Insert-Befehle sind sollte das ja "relativ rasch" über die Bühne gehen.
 

Asseon

Draic Kin

Registriert
14 Juli 2013
Beiträge
10.353
Ort
Arcadia
"einfache" Inserts sind nicht immer wirklich einfach ggf. müssen Indizes dabei aktualisiert und/oder Foriegn Keys überprüft werden.
mal eben ein konkretes Beispiel
Wir haben hier eine Datenbank die ist etwa 500 gb groß der Export dauert etwa ne Stunde aber der Import dauert mal eben 26 Stunden liegt sicherlich zum teil am schlechten Datenbank Modell aber was ich damit sagen möchte
inserts sind nicht unbedingt schnell hängt vom verwendeten dbms, den exakten db modell und ggf. der Engine ab
 

KaPiTN

♪♪♫ wild at heart ♪♫♫♪

Registriert
14 Juli 2013
Beiträge
29.138
@Larius:

Vergiß das bitte mit den 5 Threads. Ich hatte da was mit den Tasks der Integration Services in Erinnerung. Das paßt hier gar nicht hin.

Die Anzahl WorkingThreads liegt bei mindestens 256.

Aber wenn Du einen Threadpool verwendest, brauchst Du Dir doch eh keine Gedanken darüber zu machen, oder? Dafür ist der doch da.
 

Larius

OutOfOrder

Registriert
12 Juli 2013
Beiträge
5.792
  • Thread Starter Thread Starter
  • #10
Asseon, danke für die Werte. Und Kapitn, ist scho vergessen ^^
 

Kugelfisch

Nerd

Registriert
12 Juli 2013
Beiträge
2.342
Ort
Im Ozean
"einfache" Inserts sind nicht immer wirklich einfach ggf. müssen Indizes dabei aktualisiert und/oder Foriegn Keys überprüft werden.
Grundsätzlich korrekt, allerdings kann man zumindest die Überprüfung der Foreign-Key-Beziehungen ggf. mit DBMS-spezifischen Anweisungen temporär deaktivieren, sofern man sich sicher ist, dass der importierte Datenbestand konsistent ist (im Falle von MySQL und InnoDB z.B. über die Variable foreign_key_checks) - das kann den Import grosser Datenbestände mit vielen Fremdschlüssel-Abhängigkeiten signifikant beschleunigen.

Allgemein gilt, dass ein DBMS-unabhängiges Kopieren von Datenbeständen hinsichtlich der Performance und auch der gebotenen Funktionalität in vielen Fällen wesentlich schlechter ist als eine DBMS-spezifische Lösung. Neben dem offensichtlichen Exportieren und Importieren bieten diverse DBMS z.B. auch Möglichkeiten zur Live-Replikation von Datenbeständen von einem Master- auf einen oder mehrere Slave-Server. Speziell, wenn du grosse Datenbestände erwartest oder die Synchronisation regelmässig erfolgen soll, empfiehlt es sich meines Erachtens, zumindest für die bekanntesten DBMS spezifische Optimierungen zu implementieren.
 

Tryndamere

Neu angemeldet

Registriert
23 Juli 2013
Beiträge
49
Hm vl verstehe ich die Aufgabe/Problematik die du bearbeiten willst nicht ganz aber:

Die Problematik: DB 1 in DB2 kopieren.

Stellt sich mir Performancefrage nummer 1:

Warum jeden Datensatz einzeln hashen?
Prinzipiell sollte das hashen der ganzen Tabelle schneller gehen als das einzelne hashen der Datensätze. Und nachdem du sie kopiert hast vergleichst du Prüfsumme der DB 1 mit Prüfsumme der DB 2. Erst wenn hier ein Fehler auftritt gezielt die einzelnen Datensätze hashen.

Ich gehe bei der annahme davon aus das ein Fehler relativ unwahrscheinlich ist.

Das nächste was mir auffällt was ich aber nicht ganz verstehe ist warum hier über eine Anzahl von Querrys geredet wird. Wenn ich mich recht entsinne ist doch 1 großer Insert performanter als viele kleine Inserts. Warum also nicht die Daten in große Inserts zusammenführen und dann auf einmal darauf ablassen?

Der nächste Punkt den ich habe ist, warum nicht die internen Methoden benutzen für den Export bzw. Import und bei Änderung des Datenbanksystems einen Konvert darauf ablassen?

Ich habe nicht so die Erfahrung mit großen Datenbanken, das größte was ich einmal hatte waren glaub ~10 mio Einträge im Fach Data Warehouse.


Aber die Anzahl der Querrys pro sekunde finde ich ganz interessant auch wenn es mir leider etwas wenig vorkommt(damit kämpfe ich gerade sehr).

LG
 

Exterminans

Neu angemeldet

Registriert
14 Juli 2013
Beiträge
147
Dito. Die Datensätz einzeln übertragen zu wollen ist kompletter Unsinn, das ist extrem langsam, da unsäglich viel Overhead.

Es macht da auch nicht viel Sinn sich über Multithreading Gedanken zu machen, im Optimalfall lässt du dir die KOMPLETTE Tabelle nur nach P-Key (oder sogar komplett unsortiert!) ausgeben und importierst diese ebenfalls wieder als Ganzes.
Dabei beim Import Constraints und Indizes bis auf den PK deaktivieren, die kommen erst wieder drauf, wenn auch die verknüpften Tabellen fertig befüllt sind.

Die Anzahl der Threads dabei NUR soweit hoch treiben, bis entweder Disk-IO oder die Netzwerkbandbreite voll ausgelastet sind.
Der limitierende Faktor wird dabei übrigens die SCHREIB-Leistung beim Zielsystem sein. Sollte dort nicht bereits irgend eine Form der Partitionierung auf mehrere Raids zum tragen kommen, so ist dort mit deaktivierten Indizes aller Wahrscheinlichkeit nach bereits ein einziger Thread die optimale Lösung.
Eine Performancesteigerung erreichst du nur noch, indem du Netzwerk in nen zweiten Thread auslagerst, aber Inserts solltest du pro Festplattenverband nur einen einzigen parallel ausführen.

Die beste Performance liefert dabei übrigens i.d.R. nicht SQL zum Insert, sondern CSV und dann ein passender Loader / Bulk Insert. Der Wegfall des Overheads für das Parsen des Queries ist dabei nicht unerheblich und bringt dich DEUTLICH näher an den maximal möglichen Netzwerk/Disk-IO-Durchsatz.
 

Larius

OutOfOrder

Registriert
12 Juli 2013
Beiträge
5.792
  • Thread Starter Thread Starter
  • #14
@Kugelfisch: AFAIK funktioniert das mit den Slave Servern nur wenn das gleiche DBMS verwendet wird. Außerdem soll diese Portierung nicht in einem regelmäßigen Zeitraum stattfinden sondern soll 1x durchgeführt werden. Dafür wusste ich nicht das man die Keyüberprüfung ausschalten kann.

Tryndamere, die Idee basiert auf einem Projekt, welches dann doch nicht durchgeführt worden ist. Hierbei sollten mehrere Terrabyte an hochsensiblen Daten von einer DB in eine andere gespielt werden, daher auch meine ursprüngliche Idee das man jeden Datensatz hasht, diese Hashes dann gruppiert und solange die Gruppierung weiter durchführt bis für 1 Tabelle 1 Hash vorhanden ist. Wenn man nämlich dann bemerkt das ein Fehler auf der Tabelle liegt braucht man nicht lange suchen sondern kann sich durch die einzelnen Checksummen runterarbeiten bis auf den betreffenden Datensatz. Außerdem kann man sowas dann schön für ein Reporting hernehmen und dann sagen "Bei so und sovielen Daten wurde ein Fehler festgestellt".

Bzgl. dem einen großen Insert: :m mein Fehler. Ich hab echt nicht mehr daran gedacht das ich die Daten auch bündeln kann. Is scho a Zeitl her als ich in der Datenbank-Vorlesung gesessen bin. Die Idee mit dem eingebauten Export -> Parsen -> Import und dann erneut hashen finde ich recht interessant, muss ich mir mal durch den Kopf gehen lassen.
 

Tryndamere

Neu angemeldet

Registriert
23 Juli 2013
Beiträge
49
Die Idee mit dem Hashen klingt mir sehr nach einem Hashbaum. Wobei der etwas am Ziel vorbei geht, denn das Ziel in einem hashbaum ist es ja das man einen einzelnen Datensatz prüft und trotzdem eine Signatur der ganzen datenbank hat. Anwendung z.B. im Certificate Revoke Tree.

Aber freut mich das ich dich auf eine neue Idee gebracht habe

MfG
 

Larius

OutOfOrder

Registriert
12 Juli 2013
Beiträge
5.792
  • Thread Starter Thread Starter
  • #16
Eigentlich stammt die Idee vom Divide and Conquer Algorithmus bzw. Binary Search Algorithmus. Man kann direkt mit 1 Hash Value sehen ob eine Tabelle korrekt ist oder nicht und muss im Fehlerfall nur eine bestimmte Anzahl an Checksummen überprüfen anstatt die ganze Tabelle. Den Certificate Revoke Tree les ich mir morgen mal durch.
 

Tryndamere

Neu angemeldet

Registriert
23 Juli 2013
Beiträge
49
Der Certificate Revoke Tree ist eine Anwendung des Hash Trees.

Da wirst du aber nicht dazu viel finden, da er derzeit noch nicht verwendet wird.
 
Oben