Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > Генерация и заполнение бд ~60 млн. записей


Автор: NightWolf3000 27.5.2013, 09:36
Задача в сабже.
Генерация и вставка написана, но работает медленно.
Код

    private static void runFilling(PooledConnection poolledConnection,
            int maxRow, int minRow) throws UnsupportedEncodingException,
            SQLException {
        try {
         for (int j = 1; j <= count; j++) {
                    for (int i = 1; i <= count2; i++) {
                        for (int i = minRow; i < minRow+count; i++) {
                            insertNextRow(poolledConnection, SQL_INSERT_STRING);
                            insertNextRow(poolledConnection, SQL_INSERT_STRING_OTHER_TABLE);
                        }
                    }
                }
            }
        } catch (SqlIntegrityConstraintViolationException e) {
            //обрабатываю исключение
        }
    }

    private static void insertNextRow(PooledConnection poolledConnection, String insertIn) throws SQLException,
            UnsupportedEncodingException {
        Connection connection = poolledConnection.getConnection();
        PreparedStatement statement = connection.prepareStatement(insertIn
                + MAIN_SQL_INSERT_WITH_PARAMETR);
        for (int j = 1; j <= 52; j++) {
            if (j == 1)
                statement.setObject(1, "");
            else if (j == 2)
            ...
            //простыня заполнения параметрами
        }
        statement.executeUpdate();
    }


идеи по исправлению этого жуткого кода? 

Автор: danilych 27.5.2013, 17:55
что за БД, - может попробовать нативные утилиты? 

Автор: NightWolf3000 27.5.2013, 18:17
db2, появилась мысль использовать 
Код

Connection connection = poolledConnection.getConnection();
connection.setAutoCommit(false);
Statement st = connection.createStatement();
цикл st.addBatch(sql);
проверка лимита команд
st.executeBatch();
connection.commit();
st.clearBatch();
продолжение цикла


скорость увеличилась, однако на 3 итерации виснет  на st.executeBatch();

Автор: serger 28.5.2013, 07:42
Можно проверить на тестовом запросе. Драйвер обновить...

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com//object-id51a2ff8d6ccc19c47f000002#findElement_E7045_51a435d36ccc19ed73000bee_0

Автор: d_k 28.5.2013, 07:50
стейтменты стоит закрывать... да и использовать предварительно откомпиллированные запросы

Автор: serger 28.5.2013, 10:14
Тут примерчик:
http://javarevisited.blogspot.ru/2013/01/jdbc-batch-insert-and-update-example-java-prepared-statement.html
Можно для эксперементов с размером batchSize поиграться...

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com//object-id51a2ff8d6ccc19c47f000002#findElement_E7045_51a459466ccc19d63300721e_0

Автор: NightWolf3000 28.5.2013, 14:45
преобразил код, теперь около 600к записей вбрасывает за минуту, но маловата скорость все равно, долго думает на st.executeBatch();
Код

Connection connection = poolledConnection.getConnection(); 
connection.setAutoCommit(false); 
int bathcount = 0; 
Statement st = connection.createStatement(); 
for (condit){ st.addBatch(sql); 
if (bathcount >= 10000) 
{ st.executeBatch(); 
connection.commit(); 
st.clearBatch();
bathcount = 0; }
bathcount++; } }

и если я добавляю здесь  st.addBatch(sql); поочередно вставку в разные таблицы то это не сть хорошо? стоит разделить на два PreparedStatment? но пробовал на одном коннекте из пула скорость сохраняась такая же ибо стайтменты выполнялись последовательно, на двух коннектах теряется один из PreparedStatment и не дает сетить значения. За совет по обновлению драйвер благадорю, стало быстрей.

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com//object-id51a2ff8d6ccc19c47f000002#findElement_E7045_51a498c56ccc19f56e0028eb_0

Автор: serger 28.5.2013, 16:51
Цитата

   и если я добавляю здесь  st.addBatch(sql); поочередно вставку в разные таблицы то это не есть хорошо?
   

можно же по-эксперементировать, но думаю лучше однотипные запросы.
База-то какая? мб есть поддержка своих способов заливки. Или всё-таки через утилиты?

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com//object-id51a2ff8d6ccc19c47f000002#findElement_E7045_51a4b67b6ccc19c10d003dc1_0

Автор: NightWolf3000 29.5.2013, 09:16
я писал уже, база  - IBM db2. Насчет своих способов: вы подразумеваете аналог постгресовской copy? можно пример утилит на любой базе?

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com//object-id51a2ff8d6ccc19c47f000002#findElement_E7045_51a59d3b6ccc19877d00053a_0

Автор: serger 29.5.2013, 11:05
да банальный psql. Должны быть утилиты работы из командной строки.

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com//object-id51a2ff8d6ccc19c47f000002#findElement_E7045_51a5b6e56ccc19d603000cc4_0

Автор: NightWolf3000 29.5.2013, 15:50
попробовал для разных таблиц разделить следующим образом
Код

PooledConnection pooledConnection = db2ConnectionPoolDataSource.getPooledConnection();
Connection connection1 = pooledConnection.getConnection();
connection1.setAutoCommit(false);
PreparedStatement pst1 = connection1.prepareStatement(SQL_TAMPLATE);
Connection connection2 = pooledConnection.getConnection();
connection2.setAutoCommit(false);
PreparedStatement pst2 = connection1.prepareStatement(SQL_TAMPLATE_2);
for (int i = 1; i <= count; i++) {
           changedata
           fillStatment(pst1);
           changedata
           fillStatment(pst2);
           batchCounter++;
           if (batchCounter >= 10000) {
                       pst1.executeBatch();
                       pst2.executeBatch();
                       connection1.commit();
                       connection2.commit();
                       pst1.clearBatch();
                       pst2.clearBatch();
                       batchCounter = 0;
           }
}

private static void fillStatment(PreparedStatement pst1){
        pst1.setLong(1, value);
        pst1.addBatch();
    }

получил следующую ошибку com.ibm.db2.jcc.am.SqlException: [jcc][10120][10943][4.14.113] Invalid operation: statement is closed. ERRORCODE=-4470, SQLS
TATE=null  на    вот этой строчке pst1.setLong(1, value);

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com//object-id51a2ff8d6ccc19c47f000002#findElement_E7045_51a5f9a86ccc1977330030fd_0

Автор: serger 29.5.2013, 16:59
NightWolf3000, а всё-таки, через стандартные db-тулсы скорость намного быстрее?
Ещё индексы влияют на insert.

Код

if (batchCounter >= 10000) {
    pst1.executeBatch();
    pst2.executeBatch();
    connection1.commit();
    connection2.commit();
    pst1.clearBatch();
    pst2.clearBatch();
    batchCounter = 0;
}

разве так можно? ;)

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com//object-id51a2ff8d6ccc19c47f000002#findElement_E7045_51a609c66ccc195a35002eae_0

Автор: NightWolf3000 29.5.2013, 17:42
serger, через стандартные пока что не реализовал, не хватает познаний, читаю доки и статьи как их можно использовать. нужна генерация данных и сейчас она уже реализована а в стндартных пока что не нашел как генерить нужную информацию. так что проверить быстрее или нет пока что не смог.

насчет индексов проверю тогда как доберусь до базы, не помню так)

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com//object-id51a2ff8d6ccc19c47f000002#findElement_E7045_51a613db6ccc19be5b002427_0

Автор: serger 29.5.2013, 17:46
Код

psql db < data.sql

типа этого )

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com//object-id51a2ff8d6ccc19c47f000002#findElement_E7045_51a614d16ccc198b720008a0_0

Автор: batigoal 30.5.2013, 13:14
Я в своем случае шел тем же путем: сначала пробовал просто insert через PreparedStatement, потом batch, потом - batch с предварительно дропнутым индексом. А потом выкинул все и перешел на загрузку внешней утилитой (у меня был Оракл, поэтому sqlldr).

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)