1

hat ich Zeilen in eine Tabelle über JDBC mysql connection.My Tabelle einfügen wollte hat drei Spalten DISTRICT1 (Id , Name, Land) .Ich verwendete Multithreads, um den Vorgang auszuführen, und es fügte Daten in weniger als 1 Minuten ein.Dann wiederum versuchte ich, ähnliche Operation auf DISTRICT2 (ID, Name, Land) Tabelle durchzuführen In diesem Fall dauert es sehr sehr lange Zeit (mehr als 2 Stunden), um Zeilen einzufügen (genau wie es mit single thread tut). Der einzige Unterschied zwischen den Tow-Tabellen ist, dass DISTRICT2 Tabelle hat ein Feld Id, die zu anderen Tabellen durch Fremdschlüssel-Beziehung verknüpft ist während DISTRICT1 Tabelle keine solche Beziehung hat. Auch der andere Unterschied von MySQL-Engine ist, hat DISTRICT1 ENGINE = MyISAM, während es ENGINE = BDB für DISTRICT2 Ebenfalls gab es java.lang.OutOfMemoryError wenn ich PreparedStatement statt Statement .Does verwendet hat eine Beziehung mit Verbindungspooling?warum zu lange Zeit zu nehmen, Zeilen in einer MySQL-Tabelle einfügen auch nach Multithreading verwenden, wenn Tabelle eine Beziehung

Bitte sagen Sie warum es so lange dauert, wenn die Tabelle eine Beziehung habe ich denselben Programmcode verwendet einzufügen sowohl die tables.I verwendet folgenden Code, dies zu tun:

public static void main(String[] args) { 
    ExecutorService executor = Executors.newFixedThreadPool(10); 
    for (int i = 1; i <200001; i=i+10000) { 
     Runnable worker = new MyRunnable4District(i); 
      executor.execute(worker); 
     } 
    executor.shutdown(); 
} 

die Klasse MyRunnable4District wird angezeigt unter

public class MyRunnable4District implements Runnable { 
public int size; 

public MyRunnable4District(int n) { 
    this.size = n; 
} 

public void run() { 
    Connection con = null; 
    try { 

    Class.forName("com.mysql.jdbc.Driver"); 
    con = DriverManager.getConnection("jdbc:mysql://localhost/project", 
    "root", "root"); 

    String[] countries = { "ARGENTINA", "US", "UK", "INDIA", "UKRAINE", 
    "CHINA" }; 

    for (int id = size; id < size + 10001; id++) { 
    int districtId = id; 
    String districtName ="columbia"+id; 
    String districtCountry = countries[id % 6]; 
    String query="INSERT INTO district "+"VALUES ("+districtId+",'"+districtName+"','"+districtCountry+"')"; 
    //PreparedStatement stmnt =con.prepareStatement(query); 
    Statement stmnt =con.createStatement(); 
    stmnt.executeUpdate(query); 
    } 

    } catch (ClassNotFoundException e) { 
    System.out.println(e.getMessage()); 
    } catch (SQLException e) { 
    System.out.println(e.getMessage()); 
    } finally { 
    try { 
    con.close(); 
    System.out.println("thread number with size "+size+" completed"); 
    } catch (SQLException e) { 
    e.printStackTrace(); 
    } 

    } 

} 
} 

Antwort

0

Sie sind nicht aufräumen Ihre Ressourcen. Sie sollten close Ihre Aussagen, nachdem Sie sie verwendet haben.

Es wäre jedoch eine viel bessere Idee, ein PreparedStatement zu verwenden und es mit anderen Parametern wiederzuverwenden.

Sie können auch die Verwendung von LOAD DATA INFILE in Betracht ziehen.

+0

hi Mark, Wenn schließende Anweisungen das Problem ist, dann warum es gut mit Tabelle district2 ausgeführt, die keine Fremdschlüsselbeziehung hat. In diesem Fall führte es in weniger als 2min etwa 2 Millionen Zeilen erfolgreich. – nikhil

+0

@ user575854: Führen Sie den Client und den Server auf verschiedenen Computern aus? –

+0

@mark, nein ich m es auf meinem lokalen Rechner.Ich denke, das Problem ist wegen INNODB-Engine in anderen Tabelle verwendet.Klicken Sie mir die Lösung dieses Problems – nikhil

0

Sie sollten mehrwertige Einsätze versuchen. Zum Beispiel:

INSERT INTO district VALUES (id1,name1,country1),(id2,name2,country2),(id3,name3,country3); 

Dies kann eine deutliche Leistungssteigerung bietet, vor allem, wenn Sie dies tun müssen, wenn sie an einen Remote-Server zu verbinden. Neben der Reduzierung von Netzwerk-Roundtrips (oder auch von Prozessaufrufen auf einem lokalen Rechner) muss der Server weniger Abfragen verarbeiten. Wenn Sie Auto-Commit für InnoDB aktiviert haben, haben Sie jetzt eine Transaktion pro Batch statt einer pro Anweisung.

Der Connector/J JDBC-Treiber wird dies für Sie tun, wenn Sie die Option rewriteBatchedStatements auf true setzen. Ich denke, diese Funktion wurde in einer 3.1.x-Treiberversion für einfache INSERTs wie Ihres hinzugefügt. In späteren Versionen wurde rewriteBatchedStatements erweitert, um komplexere Anweisungen zu unterstützen. Suchen Sie nach this page für rewriteBatchedStatements.

Oder Sie können Ihren Code neu schreiben, um mehrwertige Insert-Anweisungen manuell zu erstellen. Eine Sache, auf die Sie achten sollten, ist die maximale Paketgröße. Sie müssen sicherstellen, dass die INSERT-Anweisung darunter bleibt. Also, machen Sie entweder max_allowed_packet sehr groß beim Importieren der Daten oder brechen Sie Ihre Chargen auf, wenn sie in der Nähe von max_allowed_packet sind.

Verwandte Themen