16 Stimmen

Oracle und JDBC-Leistung: INSERT ALL vs. preparedStatement.addBatch

Ich habe eine Java-App mit einer Oracle-Datenbank-Backend, die ich brauche, um mehrere Zeilen in einzufügen. Ich habe die Diskussion gesehen über Einfügen mehrerer Zeilen in Oracle aber ich bin auch daran interessiert, wie die Leistung beeinflusst wird, wenn JDBC in den Mix geworfen wird.

Ich sehe ein paar Möglichkeiten:

Option 1: Verwenden Sie ein PreparedStatement zum Einfügen einer einzigen Zeile und führen Sie es mehrmals aus:

String insert = "Insert into foo(bar, baz) values (?, ?)";
PreparedStatement stmt = conn.prepareStatement(insert);
for(MyObject obj : someList) {
    stmt.setString(1, obj.getBar());
    stmt.setString(2, obj.getBaz());
    stmt.execute();
}

Möglichkeit 2: Erstellen Sie eine Oracle INSERT ALL-Anweisung:

String insert = "INSERT ALL " +
    "INTO foo(bar, baz), (?, ?) " +
    "INTO foo(bar, baz), (?, ?) " +
    "SELECT * FROM DUAL";
PreparedStatement stmt = conn.prepareStatement(insert);
int i=1;
for(MyObject obj : someList) {
    stmt.setString(i++, obj.getBar());
    stmt.setString(i++, obj.getBaz());
}
stmt.execute();

Option 3: Verwenden Sie die addBatch-Funktionalität von PreparedStatement:

String insert = "Insert into foo(bar, baz) values (?, ?)";
PreparedStatement stmt = conn.prepareStatement(insert);
for(MyObject obj : someList) {
    stmt.setString(1, obj.getBar());
    stmt.setString(2, obj.getBaz());
    stmt.addBatch();
}
stmt.execute();

Ich schätze, eine andere Möglichkeit wäre, eine CSV-Datei zu erstellen und den SQL Loader zu verwenden, aber ich bin mir nicht sicher, ob das wirklich schneller wäre, wenn man den Aufwand für die Erstellung der CSV-Datei hinzurechnet...

Welche Option würde also am schnellsten funktionieren?

9voto

Ronnis Punkte 12252

Verwenden Sie die addBatch() Funktionalität von PreparedStatement für alles unter 1.000.000 Zeilen.

Jede zusätzliche Komponente, die Sie Ihrem Code hinzufügen, erhöht die Abhängigkeiten und Fehlerquellen.

Wenn Sie diesen Weg einschlagen (externe Tabellen, Sql-Loader usw.), stellen Sie sicher, dass es sich wirklich lohnt.

Die Serialisierung der Daten in eine csv-Datei und das Verschieben an einen Ort, der von der Datenbank gelesen werden kann, dauert nur etwa eine Sekunde.

In dieser Zeit hätte ich 20.000 Zeilen einfügen können, wenn ich es einfach hingenommen hätte und mit JDBC eingefügt hätte.

2voto

Lev Khomich Punkte 2237

SQL Loader scheint der bessere Weg zu sein, auch ohne direktes Laden des Pfades, aber es ist schwer zu pflegen. Batch-Insert 2-4 mal schneller als einzelne Insert-Anweisungen. Einfügen alle genau wie Batch-Insert, und beide dieser wäre schneller als PL/SQL-Implementierung.

Vielleicht möchten Sie auch lesen este AskTom-Thema.

1voto

Die Verwendung von Batch kann für einen Programmierer transparent sein. Hier ist ein Zitat aus ici :

Einstellen des Verbindungsstapelwerts

Sie können einen Standard-Batch-Wert für jede vorbereitete Oracle-Anweisung in Ihrer Oracle-Verbindung festlegen. > Verwenden Sie dazu die Methode setDefaultExecuteBatch() des OracleConnection-Objekts. Der folgende Code setzt beispielsweise den Standard-Batch-Wert für alle vorbereiteten Anweisungsobjekte, die mit dem Verbindungsobjekt conn verbunden sind, auf 20:

((OracleConnection)conn).setDefaultExecuteBatch(20);

Obwohl damit der Standard-Batch-Wert für alle vorbereiteten Anweisungen der Verbindung festgelegt wird, können Sie ihn durch den Aufruf von setDefaultBatch() für einzelne vorbereitete Oracle-Anweisungen außer Kraft setzen.

Der Verbindungsstapelwert gilt für Anweisungsobjekte, die nach dem Setzen dieses Stapelwerts erstellt wurden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X