Учебник по использованию многопоточности в 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 в зависимости от необходимости), если у вас есть несколько серверов, ну и хорошо, ваша работа теперь разделена на несколько серверов.
- Каждая строка данных асинхронно разделяется между двумя серверами и 50 beans на каждом сервере.
Вам не нужно иметь дело с потоками во всем процессе, JMS идеален, потому что ваши данные находятся в транзакции, если что-то не удастся, прежде чем вы отправляете ack на сервер, сообщение будет отправлено пользователю, нагрузка будут разделены между серверами, если вы не сделаете ничего особенного, как многопоточность.
Кроме того, spring предоставляет spring -batch, который может вам помочь. http://docs.spring.io/spring-batch/reference/html/spring-batch-intro.html#springBatchUsageScenarios