2016-05-24 30 views
1

Ich versuche Textdateien .txt mit mehr als 10.000 Zeilen pro Datei zu lesen, sie zu teilen und die Daten in Access-Datenbank mit Java und UCanAccess einzufügen. Das Problem ist, dass es jedes Mal langsamer und langsamer wird (wenn die Datenbank größer wird).Das Einfügen von Daten mit UCanAccess aus großen Textdateien ist sehr langsam

Nachdem nun 7 Textdateien gelesen und in die Datenbank eingefügt wurden, würde das Projekt mehr als 20 Minuten benötigen, um eine andere Datei zu lesen.

Ich habe versucht, nur das Lesen zu tun, und es funktioniert gut, so ist das Problem das tatsächliche Einfügen in die Datenbank.

N.B: Dies ist das erste Mal, dass ich UCanAccess mit Java verwende, weil ich festgestellt habe, dass die JDBC-ODBC Bridge nicht mehr verfügbar ist. Irgendwelche Vorschläge für eine alternative Lösung würden ebenfalls geschätzt werden.

Antwort

0

Wenn Ihre aktuelle Aufgabe einfach darin besteht, große Datenmengen aus Textdateien direkt in die Datenbank zu importieren, und keine anspruchsvollen SQL-Manipulationen erforderlich sind, können Sie die Jackcess-API direkt verwenden. Um zum Beispiel eine CSV-Datei importieren Sie so etwas tun könnte:

String csvFileSpec = "C:/Users/Gord/Desktop/BookData.csv"; 
String dbFileSpec = "C:/Users/Public/JackcessTest.accdb"; 
String tableName = "Book"; 

try (Database db = new DatabaseBuilder() 
     .setFile(new File(dbFileSpec)) 
     .setAutoSync(false) 
     .open()) { 

    new ImportUtil.Builder(db, tableName) 
      .setDelimiter(",") 
      .setUseExistingTable(true) 
      .setHeader(false) 
      .importFile(new File(csvFileSpec)); 

    // this is a try-with-resources block, 
    //  so db.close() happens automatically 
} 

Oder, wenn Sie brauchen, um manuell jede Eingabezeile zu analysieren, eine Zeile einzufügen, und rufen Sie den Autowert für die neue Zeile , dann würde der Code aussehen:

String dbFileSpec = "C:/Users/Public/JackcessTest.accdb"; 
String tableName = "Book"; 
try (Database db = new DatabaseBuilder() 
     .setFile(new File(dbFileSpec)) 
     .setAutoSync(false) 
     .open()) { 

    // sample data (e.g., from parsing of an input line) 
    String title = "So, Anyway"; 
    String author = "Cleese, John"; 

    Table tbl = db.getTable(tableName); 
    Object[] rowData = tbl.addRow(Column.AUTO_NUMBER, title, author); 
    int newId = (int)rowData[0]; // retrieve generated AutoNumber 
    System.out.printf("row inserted with ID = %d%n", newId); 

    // this is a try-with-resources block, 
    //  so db.close() happens automatically 
} 

eine bestehende Reihe auf ihren Primärschlüssel basiert zu aktualisieren, würde der Code

Table tbl = db.getTable(tableName); 
Row row = CursorBuilder.findRowByPrimaryKey(tbl, 3); // i.e., ID = 3 
if (row != null) { 
    // Note: column names are case-sensitive 
    row.put("Title", "The New Title For This Book"); 
    tbl.updateRow(row); 
} 

sein Beachten Sie, dass ich für die maximale Geschwindigkeit beim Öffnen der Datenbank .setAutoSync(false) verwendet habe. Beachten Sie jedoch, dass die Deaktivierung von AutoSync die Wahrscheinlichkeit erhöht, dass die Access-Datenbank in einem beschädigten (und möglicherweise unbrauchbaren) Zustand verbleibt, wenn die Anwendung während der Ausführung der Updates abnormal beendet wird.

+0

danke, aber ich muss die Datei teilen und Teilstring in jeder Zeile verwenden, so dass SQL-Abfragen und String-Splitting erfordern. –

+0

@Yassine - Wenn Sie SQL (z. B. über PreparedStatement) verwenden, um jeweils eine Zeile einzufügen, können Sie dasselbe Ergebnis auch mit Jackcess und seiner AddRow-Methode erzielen. Auf diese Weise können Sie den UCanAccess-/HSQLDB-Overhead vermeiden. –

+0

Ja, ich verwende PreparedStatement, um jede Zeile (basierend auf ihren ersten 3 Zeichen) einzufügen, nachdem sie mit SubString geteilt und in Variablen gespeichert wurde. Wie kann ich die Methode Jackcess und addRow verwenden? N.B: Ich verwende AUTO_GENERATED_KEY, um den Primärschlüssel der eingefügten Zeile zurückzugeben, um es nach dem Einfügen zu verwenden. hat die addRow-Methode diese Option? –

0

Wenn Sie auch slq/ucanaccess verwenden müssen, müssen Sie setAutocommit (false) auf der Verbindung am Anfang aufrufen und jeden 200/300-Datensatz festschreiben. Die Aufführungen werden sich dramatisch verbessern (ca. 99%).

+0

wie ein Commit jedes 200/200 Rekord machen? –

+0

Zähle einfach und rufe die Verbindung nur dann auf, wenn der Zähler sagt, dass du bereits 200 Datensätze eingefügt hast ... – jamadei