DBMS Benchmarking

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • DBMS Benchmarking

    Nabend, oder sagen wir besser "guten Morgen",

    ich habe mal wieder etwas Arbeit vor mir. Die Aufgabe lautet für ein bestimmtes DBMS ein Benchmark-Tool zu schreiben (Und verdammt, ich muss es in Java machen, wovon ich mal so gar kein Plan habe ~.~).
    Naja, was das DBMS angeht, so habe ich mich für MySQL entschieden. Die Aufgabe besteht nun konkret darin, vier Relationen mit Daten zu füllen und anschließend Operationen auf diese auszuführen. Gemessen wird die Zeit pro Operation. Natürlich muss ich das Programm und auch den Datenbankserver soweit optimieren, dass mein gewähltes DBMS am besten abschneidet (Andere Gruppen haben halt DB2, Oracle, M$ SQL o.a. gewählt). Die Optimierung des MySQL Servers spielt auch jetzt mal eher weniger eine Rolle.

    Zunächst also muss ich Daten in die Relationen eintragen. An sich ist nur eine der Relationen relevant. Hier müssen nämlich 100.000*n Tupel (n = 5; 15; 25) eingetragen werden. Gesagt, getan .. alles funktioniert, es dauert mir nur zu lang. Auf meinem relatiev veralteten Notebook habe ich zunächst für 1000 Executions mit PreparedStatements 38 Sekunden gebraucht. Anschließend habe ich es geschafft mit einfacheren Statements auf 1000 Executions / 36 Sekunden zu kommen.
    Mein momentanes Vorgehen ist mit einer Schleife 100.000*n mal die Funktion "query" aufzurufen, welche die Tupel einträgt (Die Tupel unterscheiden sich lediglich von der ID, sowie eines anderen zufällig gewählten Wertes, der zwischen 1 und n liegt).

    Hier mal die query-Funktion:
    Vorher mit PreparedStatements:

    Quellcode

    1. protected PreparedStatement stmt;
    2. [...]
    3. public void query(String query) throws SQLException {
    4. stmt = conn.prepareStatement(query);
    5. stmt.execute();
    6. stmt.clearParameters();
    7. conn.commit();
    8. }


    Nachher mit einfachen Statements:

    Quellcode

    1. protected Statement st;
    2. [...]
    3. st = conn.createStatement();
    4. [...]
    5. public void query(String query) throws SQLException {
    6. st.executeUpdate(query);
    7. conn.commit();
    8. }



    Nun ist halt zunächst mal meine Frage ob ich die PreparedStatements richtig nutze. Immerhin habe ich mehrere hundertausend Statements, die sich lediglich um zwei Attribute unterscheiden (Und das sind Integerwerte) und ich führe für jeden INSERT INTO Befehl ein prepareStatement sowie clearParameters() aus.
    Dann ist meine Frage wie ich in Java in einem solchen Falle am besten vorgehen kann bzw. ob ich mit den einfachen Statements schon ganz gut voran komme.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von Blue ()

  • Moinmoin, MySQL bietet bestimmt nicht die wenigsten Möglichkeiten an die Aufgabe heran zu gehen :D

    Blue schrieb:

    die sich lediglich um zwei Attribute unterscheiden

    Wo bindest du diese Integerwerte denn?

    Das sollte so aussehen:

    Quellcode

    1. private PreparedStatement stmt;
    2. public void Konstruktur(String query) {
    3. PreparedStatement p = con.prepareStatement("INSERT INTO foo VALUES(?,?);");
    4. stmt = conn.prepareStatement(query);
    5. }
    6. public void query(int val1, int val2) {
    7. stmt.setInt(1, val1);
    8. stmt.setInt(2, val2);
    9. stmt.execute();
    10. }
    Alles anzeigen


    Ansonsten ein paar Tipps aus der MySQL Trickkiste:
    1) Ein Nadelöhr ist der Netzwerkoverhead. Es macht also Sinn die Statements in einen großen String zu verpacken (INSERT INTO foo VALUES (1,2),(3,4),(5,6))
    2) Was macht einzelne Inserts außerdem langsam? Richtig, dass die Schlüssel und Indizes NACH JEDEM Insert neu geschrieben werden müssen.
    Führe vorher mal ein ALTER TABLE foo DISABLE KEYS durch. (Danach natürlich ENABLE KEYS nicht vergessen.)
    Dann wird der Index mit einem mal neu geschrieben.
    3) Wenn du keine Fremdschlüssel mit Auto-Increment brauchst, dann lohnt auch ein INSERT DELAYED INTO. Hier werden die INSERTs erst gesammelt und gebündelt ausgeführt. Bei welcher Größe das passiert kann man in der MySQL Konfiguration festlegen.
    4) Zusätzlich kannst du in den Tabellenoptionen noch DELAY KEY WRITE auf aktiv setzen. Wie der Name schon sagt, werden die Schlüssel dann verzögert geschrieben.
    5) Spaltentypen - hast du wirklich überall den richtigen Spaltentyp gewählt? UNSIGNED INTEGER falls nur Ganzzahlen gebraucht werden. Stimmen die Längen?
    Gerade beim Index ist die Größe wichtig.
    6) Welche Storage Engine nutzt du? MyISAM hat einen geringen Overhead. Die Tabelle lässt sich schnell vollballern. Allerdings sperrt MyISAM im Gegensatz zu InnoDB die ganze Tabelle während des INSERTS (InnoDB sperrt Zeilenbasiert). Ein weiterer interessanter Benchmark wäre die Storage Engine MEMORY zu verwenden. Allerdings solltest du nach getaner Arbeit alles mit ALTER TABLE ENGINE MyISAM wieder dafür sorgen, dass die Daten auf Festplatte geschrieben werden.