Учебник по использованию многопоточности в jdbc

Наша компания имеет пакетное приложение, которое работает каждый день. В основном он работает с базами данных, импортирует данные в таблицу базы данных из файла.

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

Для завершения всех задач требуется 3 ~ 7 часов. Я думаю, что это слишком долго, поэтому я думаю, что, возможно, я могу улучшить производительность благодаря многопоточности.

Я думаю, что, поскольку есть зависимость между задачами, это не хорошо (или это не легко), чтобы задачи выполнялись параллельно, но, возможно, я могу использовать многопоточность для повышения производительности внутри задачи.

например: у нас есть задача, определенная как "ImportBizData", которая копирует данные в таблицу базы данных из файла данных (обычно содержит 100,0000+ строк). Интересно, стоит ли использовать многопоточность?

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

Ответы

Ответ 1

Многопоточность улучшит вашу производительность, но вам нужно знать пару вещей:

  • Каждый поток нуждается в собственном соединении JDBC. Соединения не могут быть разделены между потоками, потому что каждое соединение также является транзакцией.
  • Загружайте данные в куски и commit один раз в то время, чтобы избежать накопления огромных таблиц отката/отмены.
  • Сокращение задач на нескольких рабочих единицах, где каждый блок выполняет одно задание.

Чтобы продумать последний пункт: в настоящее время у вас есть задача, которая читает файл, анализирует его, открывает соединение JDBC, выполняет некоторые вычисления, отправляет данные в базу данных и т.д.

Что вы должны сделать:

  • Один (!) поток, чтобы прочитать файл и создать из него "задания". Каждая работа должна содержать небольшую, но не слишком маленькую "единицу работы". Вставьте их в очередь
  • Следующий поток ждет (-ы) для заданий в очереди и выполняет вычисления. Это может произойти, когда потоки на шаге # 1 ждут медленного жесткого диска для возврата новых строк данных. Результат этого шага преобразования переходит в следующую очередь
  • Один или несколько потоков для загрузки данных через JDBC.

Первый и последний потоки довольно медленные, потому что они связаны с I/O (жесткие диски медленны, а сетевые соединения еще хуже). Плюс вставка данных в базу данных - очень сложная задача (выделение пространства, обновление индексов, проверка внешних ключей)

Использование разных рабочих потоков дает вам много преимуществ:

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

Ответ 2

Многопоточность может помочь, если строки некоррелированы, вы можете начать два процесса с одной строки чтения, еще одну неровную линию и получить ваше соединение db из пула соединений (dbcp) и проанализировать производительность. Но сначала я бы исследовал, является ли jdbc лучшим подходом, обычно базы данных оптимизировали решения для импорта, подобные этому. Эти решения также могут временно переключаться на проверку ограничений вашей таблицы и впоследствии возвращать их обратно, что также отлично подходит для производительности. Как всегда в зависимости от ваших требований.

Также вы можете захотеть проверить весеннюю комбинацию, которая предназначена для пакетной обработки.

Ответ 3

Насколько я знаю, JDBC Bridge использует синхронизированные методы для сериализации всех вызовов ODBC, поэтому использование mutliple threads не даст вам никакого повышения производительности, если оно не улучшит ваше приложение.

Ответ 4

Я не так хорошо знаком с JDBC, но в отношении многопоточного бита вашего вопроса, что вы должны иметь в виду, так это то, что параллельная обработка зависит от эффективного разделения вашей проблемы на биты, которые независимы друг от друга и каким-то образом ставят их (вместе с их выходом). Если вы не знаете базовых зависимостей между задачами, у вас могут быть действительно странные ошибки/исключения в вашем коде. Хуже того, все может выполняться без каких-либо проблем, но результаты могут быть от истинных значений. Многопоточность - это сложный бизнес, способный научиться (по крайней мере, я так думаю), но боль в шее, когда все идет на юг.

Вот несколько ссылок, которые могут быть полезны:

Если вы серьезно относитесь к тому, чтобы приложить усилия к многопоточности, я могу порекомендовать GOETZ, BRIAN: JAVA CONCURRENCY, действительно потрясающую книгу.

Удачи.

Ответ 5

У меня была похожая задача . Но в моем случае все таблицы не были связаны друг с другом.

STEP1: Использование SQL Loader (Oracle) для загрузки данных в базу данных (очень быстро) или любых подобных инструментов массового обновления для вашей базы данных.

STEP2: Выполнение каждого процесса загрузки в другом потоке (для несвязанных задач) и в одном потоке для связанных задач.

P.S. Вы могли бы идентифицировать различные связанные между собой задания в своем приложении и классифицировать их в группах; и запускать каждую группу в разных потоках.

Ссылки для запуска:

JAVA Threading следуйте последнему примеру в приведенной выше ссылке (Пример: разбиение большой задачи на несколько потоков)

SQL Loader может значительно повысить производительность

Ответ 6

Самый быстрый способ, с помощью которого я ввел большое количество записей в Oracle, - это операции с массивами. См. Метод setExecuteBatch, который относится к OraclePreparedStatement. Это описано в одном из примеров: http://betteratoracle.com/posts/25-array-batch-inserts-with-jdbc

Ответ 7

Если многопоточность будет осложнять вашу работу, вы можете перейти с помощью обмена сообщениями Async. Я не полностью осведомлен о ваших потребностях, поэтому следующее из того, что я вижу в настоящее время.

  • Создайте файл-читатель java, цель которого - прочитать файл biz и поместить сообщения в очередь JMS на сервере. Это может быть простая Java со статическим void main()
  • Расходуйте сообщения JMS в управляемом сообщением beans (вы можете установить ограничение на количество beans, которое должно быть создано в пуле, 50 или 100 в зависимости от необходимости), если у вас есть несколько серверов, ну и хорошо, ваша работа теперь разделена на несколько серверов.
    1. Каждая строка данных асинхронно разделяется между двумя серверами и 50 beans на каждом сервере.

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

Кроме того, spring предоставляет spring -batch, который может вам помочь. http://docs.spring.io/spring-batch/reference/html/spring-batch-intro.html#springBatchUsageScenarios