2011-02-04 16 views
11

Mam aplikację java z zapleczem bazy danych Oracle, w której muszę wstawić wiele wierszy. Widziałem dyskusję na temat inserting multiple rows into Oracle, ale jestem również zainteresowany tym, w jaki sposób wpływ na wydajność ma JDBC wrzucony do miksu.Wydajność Oracle i JDBC: INSERT ALL vs preparedStatement.addBatch

Widzę kilka możliwości:

Wariant 1: Użyć singe-wiersz wstawić PreparedStatement i wykonać go wielokrotnie:

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(); 
} 

Opcja 2: Budowanie wyrocznią wprowadzeniu wszystkich oświadczenie:

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(); 

Opcja 3: Użyj funkcji addBatch w 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(); 

Chyba Inną możliwością byłoby utworzyć plik CSV i korzystać z SQL Loader, ale nie jestem pewien, że rzeczywiście byłoby szybciej, jeśli dodać w napowietrznej tworzenia pliku CSV ...

Która z opcji będzie działać najszybciej?

+2

Proszę udostępnić wyniki pomiarów. Zauważ, że Oracle ma ograniczenie wielkości partii. Jeśli się nie mylę, jest to 1000 rekordów na raz, więc musisz wywoływać 'executeBatch()' co 1000 rekordów. Powiązane: http://stackoverflow.com/questions/2467125/reusing-a-preparedstatement-multiple-times – BalusC

+0

Mam sukcesywnie używane partie o wielkości 2500, ale nie widziałem realnej poprawy wydajności przekraczającej rozmiar 500 –

Odpowiedz

7

Skorzystaj z funkcji AddBatch w PreparedStatement dla wszystkiego poniżej 1 000 000 wierszy.

Każdy dodatkowy komponent dodawany do kodu zwiększa zależności i punkty awarii. Jeśli pójdziesz tą trasą (zewnętrzne tablice, sql loader etc) upewnij się, że naprawdę warto.

Szeregowanie danych do pliku csv, przeniesienie go do lokalizacji, którą można odczytać za pomocą bazy danych, może trochę potrwać. W tym czasie mogłem wstawić 20 000 wierszy, jeśli tylko je zassałem i zacząłem wstawiać z JDBC.

2

SQL Loader wydaje się być lepszy nawet bez bezpośredniego ładowania ścieżki, ale trudno go utrzymać. Wsadka wsadowa 2-4 razy szybsza niż instrukcja pojedynczego wkładu. Włóż wszystko tak, jak wkładkę wsadową, a oba te elementy byłyby szybsze niż implementacja PL/SQL.

Możesz również przeczytać artykuł na temat AskTom: this.

+0

w moim przypadku, wsadowy wsad był ponad 100 razy szybszy niż wkładka pojedyncza. –

1

Używanie partii może być przezroczyste dla programisty. Oto cytować z here:

Ustawianie Batch połączeń Wartość

Można określić domyślną wartość dla każdej partii Oracle przygotowane oświadczenie w związku Oracle. > Aby to zrobić, użyj metody setDefaultExecuteBatch() obiektu OracleConnection. Na przykład poniższy kod ustawia domyślną wartość partii na 20 dla wszystkich przygotowanych obiektów instrukcji powiązanych z obiektem połączenia conn:

(połączenie (OracleConnection)) .setDefaultExecuteBatch (20);

Mimo że ustawia domyślną wartość partii dla wszystkich przygotowanych wyciągów połączenia, można go przesłonić, wywołując funkcję setDefaultBatch() dla indywidualnych instrukcji przygotowanych przez Oracle.

Wartość wsadu połączenia zostanie zastosowana do obiektów instrukcji utworzonych po ustawieniu tej wartości wsadowej.