Announcement

Collapse
No announcement yet.

Programm wird immer langsamer

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Programm wird immer langsamer

    Hallo,

    ich bin neu im Forum und hoffe, dass ihr mir vielleicht helfen könnt. Seit einer Woche versuche ich, ein Programm zu optimieren und finde keinen Weg, dass es sein Tempo behält und nicht immer langsamer wird.

    Kurz zum Programm. Ich möchte ein Programm schreiben, welches Daten von einer ODBC-Datenbank in eine andere transferiert. Im Konkreten Fall von einer ADS-Datenbank in eine MySQL-Datenbank.
    Der Programmabschnitt, welcher immer langsamer wird ist derjenige, der aus dem Resultset der Abfrage den Insert-Query erzeugt.
    Zuerst habe ich es mit einer Stringverkettung versucht, anschließend mit Vectoren, jetzt zum Schluss mit einem Stringbuilder, auf den mich Google gebracht hat. Aller x-hundert Einträge leere ich die Variablen und führe das Insert-Query auf, in der Hoffnung, dass der Garbage-Collector Aufräumt und die Geschwindigkeit wieder gegeben ist.

    Für die ersten 800 Datensätze erstellt er recht flott das Insert-Query, anschließend wird er immer langsamer, bis er schließlich im Sekundentakt die Datensätze verarbeitet = unererträglich und nicht praxistauglich. Anbei der Quelltext - ich habe versucht, ihn gut zu kommentieren und übersichtlich zu gestalten:

    Code:
    private void generateInsertQueryFromResultSet(ResultSet resultSet, TableColumn[] tableColumns, String tableName) throws SQLException
    {
    	StringBuilder stringBuilder = new StringBuilder();
    	// Insert-Header hinzufügen ( Also das INSERT INTO TABELLE
    	// (Spalte1,Spalte2,...) VALUES )
    	stringBuilder.append(getInsertQueryHeader(tableColumns, tableName));
    
    	int j = 0;
    	// Gehe durch alle einzelnen Datensätze
    	while (resultSet.next())
    	{
    		/*
    		 * Alle 200 Datensätze nimm das Insert-Query und führe es aus.
    		 * Anschließend leere den Stringbuffer und fülle ihn erneut iterativ
    		 */
    		if ((j % 200 == 0) && (j > 0))
    		{
    			System.out.println("Datensatz " + j + " von Tabelle " + tableName);
    			// Insert-Query ausführen
    			doInsertQueryToNewTable(stringBuilder.toString());
    			// Reinitialisieren der Variable um Speicherplatz frei zu
    			// schaufeln (leider ohne Erfolg)
    			stringBuilder = new StringBuilder();
    			// Wieder Insert-Header hinzufügen ( Also das INSERT INTO
    			// TABELLE (Spalte1,Spalte2,...) VALUES )
    			stringBuilder.append(getInsertQueryHeader(tableColumns, tableName));
    
    		} else if (j > 0)
    		{// Wenn nicht erster Datensatz, füge Komma für vorherige Zeile ein
    			stringBuilder.append(",\r\n");
    		}
    		/*
    		 * Beginn neuer Datensatz Value-Abschnitt des Querys (Values
    		 * (Value1, Value2,...) )
    		 */
    		// KLammer auf
    		stringBuilder.append("( ");
    
    		for (int i = 0; i < tableColumns.length; i++)
    		{
    			// Wert des Feldes / die Funktion enthält eine Switch-Klausel,
    			// welche Datentypgerecht in einen String umwandelt)
    			stringBuilder.append(getInsertValueString(tableColumns[i], resultSet));
    			// Ich habe mal versucht, die Funktion durch einen pauschalen
    			// String zu ersetzen: Kein Geschwindigkeitsgewinn
    			// stringBuilder.append("WERT");
    			if ((i + 1) != tableColumns.length)
    			{
    				// Zwischen den Werten ein Komma einfügen
    				stringBuilder.append(", ");
    			}
    		}// ENDE FOR
    		// Ende Zeile / Value-Eintrag --> Klammer Zu und Zeilenumbruch
    		stringBuilder.append(")\r\n");
    		j++;
    	}// ENDE WHILE
    }
    Ich verstehe nicht, warum er langsamer wird?

    Könnt ihr mir helfen, warum er langsamer wird und was ich dagegen tun kann?

    Danke und viele Grüße,

    Matthias

  • #2
    Wieso ODBC? Für ADS würde ich den JDBC-Treiber verwenden und wenn möglich einen forward-only-Curser so das die bearbeiteten Result-Datensätze nicht gecacht werden.

    Comment


    • #3
      Hallo Bernhard Geyer,
      Der Zugriff über ODBC ist einfacher umzusetzen, weil ich den ODBC-Treiber in Windows eingerichtet habe und vorher mit meinen PHP-Skripten auf die Datenbank-Dateien (ADS = DBF-Dateien) zugreifen konnte.

      Den JDBC-Datenbanktreiber gibt es soweit ich weiß nur Lizenzpflichtig, weshalb ich ODBC nutze. Allerdings scheint die Geschwindigkeitsbremse nicht am ResultSet zu liegen - zumindest habe ich das Problem nicht, wenn ich die Informationen einfach nur stupide in ein HashMap speichere - das stupide Speichern funktioniert ohne Probleme.

      Viele Grüße,

      Matthias

      *UPDATE*

      Ich sehe gerade Du hast mir einen JDBC-Treiberlink geschickt. Ich habe nur den ADS 8.x, werde es aber mit Deinem Link mal probieren, ob ich klar komme. Danke - auch wenn ich nicht glaube, dass es mein Problem löst - aber wir werden sehen

      Comment


      • #4
        Wievie Speicher gönnst du der JVM? Ev. benötigt du viel Speicher, der wird langsam voll und die JVM ruft verzweifelt immer den GarbageCollector auf...
        Christian

        Comment


        • #5
          Läuft das ganze in einer Transaktion? Wieviel Speicher darf sich der MySQL genehmigen (ist teilweise bei Desktop-Installationsmodus sehr konvervativ).

          Comment


          • #6
            Hallo,

            es läuft nicht in einer Transaktion soweit ich weiß. Ich bin noch garnicht soweit, mit mySQL zu connection und zu inserten (und wenn doch, ändert das nichts an der Geschwindigkeit).

            Ich habe nur eine Verbindung zur ADS-Datenbank über ODBC. Über JDBC bekomme ich es beim besten Willen nicht zum Laufen.

            Viele Grüße,

            Matthias

            Comment


            • #7
              Stell mal den Code auf prepared Statements um so das der Querystring nicht so lange wird. Das zusammenbauen von Strings (trotz stringbuilder) ist nicht gerade eine Stärke von managed umgebungen wie Java oder .NET und kann schon bremsen bei langen Strings.

              Comment


              • #8
                Originally posted by Bernhard Geyer View Post
                Stell mal den Code auf prepared Statements um so das der Querystring nicht so lange wird. Das zusammenbauen von Strings (trotz stringbuilder) ist nicht gerade eine Stärke von managed umgebungen wie Java oder .NET und kann schon bremsen bei langen Strings.
                Super Idee :-) - davon hatte ich noch nie was gehört vorher. Ich werde dann mal berichten ob es geklappt hat

                Danke erstmal und viele Grüße,

                Matthias

                Comment


                • #9
                  Hallo nochmal,

                  ich habe es auf prepared Statements umgestellt und es hat prima geklappt. Das Programm rennt jetzt ordentlich durch.

                  Vielen Dank nochmal für Deine/Eure Hilfe.

                  Viele Grüße,

                  Matthias

                  Comment

                  Working...
                  X