Быстрая загрузка JDBC - OutOfMemory после 20 миллионов операций addBatch () - PullRequest
0 голосов
/ 07 октября 2011

Я использую драйвер Teradata jdbc 13.00.00.10 и пытаюсь загрузить плоский файл со 100 миллионами строк в teradata.

Я начинаю с чистого стола.

Сначала я попытался перебрать весь файл, сделать addBatch () для каждой строки, и только в конце сделать один executeBatch ():

        while ((s = reader.readLine())!=null ){
            String[] columns = StringUtils.split(s, separator);
            for (int j=0; j <columns.length; j++){
                st.setString(j+1,columns[j]);
            }
            st.addBatch();
            i++;
            if (i % 10000 ==0 ){
                ULogger.info(this, "imported " + i + " lines.");
            }

        }
        st.executeBatch();

Это быстро потребляет всю память для моего приложения.

Я установил 9 Гб XMX и получил OutOfMemory после ~ 40 миллионов addBatch ().

Затем я попытался периодически выполнять executeBatch () - итерация по файлу, и каждые 20 миллионов addBatch () выполняют executeBatch ().

       while ((s = reader.readLine())!=null ){
            String[] columns = StringUtils.split(s, separator);
            for (int j=0; j <columns.length; j++){
                st.setString(j+1,columns[j]);
            }
            st.addBatch();
            i++;
            if (i % 20000000 ==0 ){
                   st.executeBatch();

                   st.clearWarnings();
            }

        }
        st.executeBatch();

В этом случае первый executeBatch () завершился успешно.

Однако, вторая функция executeBatch () завершилась неудачно, с ошибкой "при запуске FastLoad таблицы базы данных XXX".

Может кто-нибудь объяснить, как я должен загрузить 100 миллионов строк?

Есть ли какая-то конфигурация, которую мне не хватает (например, чтобы драйвер периодически отправлял обновления и не держал их в памяти)?

Спасибо

A.

1 Ответ

2 голосов
/ 08 октября 2011

Получил ответ на форуме пользователей Teradata, который направил меня в FAQ - (http://developer.teradata.com/connectivity/faq), где говорится, что правильный способ работы - периодически вызывать executeBatch (); однако для этого необходимо сначала отключить автокоммит на соединении, и убедитесь, что передали в конце.

так что мой код теперь выглядит так:

        **con.setAutoCommit(false);**
        while ((s = reader.readLine())!=null ){
            String[] columns = StringUtils.split(s, separator);
            for (int j=0; j <columns.length; j++){
                st.setString(j+1,columns[j]);
            }
            st.addBatch();
            i++;
            if (i % 20000000 ==0 ){
                   st.executeBatch();

                   st.clearWarnings();
            }

        }
        st.executeBatch();
        **con.commit();**

работает как шарм.

Единственное, что не совсем понятно из FAQ - это какой размер чанка должен быть. он говорит что-то сбивающее с толку, например: «настолько большой, насколько может выдержать ваша куча JVM», а также «в будущем мы будем рекомендовать установить его равным 50–100 тыс.». рабочая находка.

Кроме того - очевидно, что в Teradata JDBC есть функция быстрого загрузчика CSV - см. http://developer.teradata.com/doc/connectivity/jdbc/ reference / current / jdbcug_chapter_2.html # BABFGFA2 - которая в целом может повысить производительность.

...