высокая производительность в спящем режиме, вставляют

Я работаю над задержкой чувствительная часть приложения, в основном я получу сетевое событие, преобразовывают данные и затем вставляют все данные в DB. После профилирования я вижу, что в основном все мое время проведено, пытаясь сохранить данные. вот код

private void insertAllData(Collection<Data> dataItems)
{
    long start_time = System.currentTimeMillis();
    long save_time = 0;
    long commit_time = 0;
    Transaction tx = null;
    try
    {
        Session s = HibernateSessionFactory.getSession();
        s.setCacheMode(CacheMode.IGNORE);
        s.setFlushMode(FlushMode.NEVER);
        tx = s.beginTransaction();
        for(Data data : dataItems)
        {
            s.saveOrUpdate(data);
        }
        save_time = System.currentTimeMillis();
        tx.commit();
        s.flush();
        s.clear();
    }
    catch(HibernateException ex)
    {
        if(tx != null)
            tx.rollback();
    }
    commit_time = System.currentTimeMillis();
    System.out.println("Save: " + (save_time - start_time));
    System.out.println("Commit: " + (commit_time - save_time));
    System.out.println();
}

Размер набора всегда - меньше чем 20. вот данные синхронизации, которые я вижу:

Save: 27
Commit: 9

Save: 27
Commit: 9

Save: 26
Commit: 9

Save: 36
Commit: 9

Save: 44
Commit: 0

Это сбивает с толку меня. Я полагаю что save должно быть быстрым и все время должен быть потрачен на commit. но ясно я неправ. Я также попытался удалить транзакцию (не действительно необходимый), но я видел худшие времена... Я установил, в спящем режиме jdbc.batch_size=20...

Я могу ожидать получать целых 500 сообщений/секунда, таким образом, мне будет нужна единственная обработка сообщений для нахожений под 20 миллисекундами.

мне нужна эта операция, чтобы быть максимально быстро, идеально только было бы одно распространение в прямом и обратном направлениях к базе данных. Как я могу сделать это?

16
задан luke 12 June 2010 в 00:15
поделиться

3 ответа

Отодвиньте генерацию первичного ключа от автоматического увеличения на стороне сервера. Ваш Java-код должен отвечать за генерацию PK, чтобы избежать обходов.

Для приличной производительности массовой вставки вам нужен метод, которому не нужно обращаться к базе данных при каждом вызове saveOrUpdate. Использование UUID в качестве первичного ключа или реализация HiLo может помочь в достижении этого. В противном случае массовая вставка не происходит.

Оптимизаторы объединенные или объединенные-ло являются лучшим выбором для обеспечения производительности и взаимодействия с другими внешними системами.

16
ответ дан 30 November 2019 в 22:23
поделиться

Честно говоря, я не знайте, что можно сделать разумный вывод из вашего теста и из «мер», которые вы показываете (я подозреваю, что много накладных расходов из-за разминки, коллекция очень мала, а выборка очень мала).

В любом случае, я могу сказать вам, что ваш текущий код не будет масштабироваться, и вы, скорее всего, взорвете Сессию при передаче более крупной коллекции. Вам необходимо очищать сеанс через равные промежутки времени (каждые 20 записей, если размер пакета равен 20).

На самом деле, я рекомендую прочитать целиком главу 13. Пакетная обработка .

3
ответ дан 30 November 2019 в 22:23
поделиться

Некоторые базовые вещи:

  • Есть ли у вас триггеры или ограничения внешнего ключа без индекса? ограничения без индекса?
  • Есть ли у вас пакетные драйверы?
  • Работают ли ваши драйверы в пакетном режиме (см. hibernate.jdbc.batch_size из ссылки Паскаля)?
  • Есть ли индексы в ваших таблицах (если у вас много индексов, это может иногда замедлять вставку)?

Пакетная обработка является частью JDBC 2.0, она позволяет вам выполнять несколько операторов в "пакете"; идея состоит в том, чтобы уменьшить задержку при обходе (вы можете выполнять несколько пакетов за транзакцию).

Statement stmt = dbCon.createStatement("insert into DataTable values (?,?,?)");
stmt.setInt(1, x1); stmt.setInt(2, x2), stmt.setString(3, "some value");
stmt.addBatch();
...
stmt.setInt(1, x2); stmt.setInt(2, x3), stmt.setString(3, "some other value");
stmt.addBatch();

stmt.executeBatch();
dbCon.commit();

Возможно, вы можете использовать это в качестве эталонного теста. Я бы также посмотрел на SQL, который генерирует hibernate, чтобы увидеть, выполняет ли он запрос на вставку для получения сгенерированных идентификаторов.

0
ответ дан 30 November 2019 в 22:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: