Процесс Java ETL

#java #hibernate #jdbc #etl

#java #переход в спящий режим #jdbc #etl

Вопрос:

У меня есть эта новая задача — загрузить ~ 100 миллионов строк из базы данных Oracle и вставить их на удаленный сервер базы данных MySQL.

Я разделил проблему на две части:

  1. серверный сервер REST, отвечающий за загрузку данных на сервер MySQL;
  2. Java-приложение на стороне клиента, которое отвечает за загрузку источника данных Oracle.

На стороне Java я использовал обычный JDBC для загрузки содержимого с разбиением на страницы и передачи его по проводам на сервер. Этот подход работает хорошо, но он делает код громоздким и не очень масштабируемым, поскольку я сам разбиваю страницы на страницы, используя Oracle ROWNUM…..ГДЕ ROWNUM> x и ROWNUM < y.

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

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

Заранее спасибо.

Обновить

Спасибо за бесценные предложения. Я выбрал использование SpringBatch для загрузки данных из базы данных Oracle, потому что среда довольно плотная, и у меня нет доступа к набору инструментов Oracle. SpringBatch — это trie и true. Для этапа записи данных я выбрал запись фрагментов записей с использованием файла ЗАГРУЗКИ ДАННЫХ MySQL, как вы все заявили. Службы REST находятся посередине, поскольку они скрыты друг от друга по соображениям безопасности.

Комментарии:

1. Просто используйте пакет spring. Не изобретайте что-то для решения задачи. Если у вас есть какие-либо поля SQL Server, лежащие вокруг, SSIS также отлично справится с этой задачей для вас.

Ответ №1:

100 миллионов строк — это довольно много. Вы можете спроектировать его множеством способов: REST-серверы, чтение JDBC, пакет Spring, интеграция Spring, спящий режим, ETL. Но суть в следующем: время.

Независимо от того, какую архитектуру вы выберете, вам в конечном итоге придется выполнять эти INSERT s в MySQL. Ваш пробег может варьироваться, но просто для того, чтобы дать вам порядок величины: при 2 тыс. вставок в секунду потребуется полдня, чтобы заполнить MySQL 100 МЛН строк (источник).

Согласно тому же источнику LOAD DATA INFILE , может обрабатывать около 25 тыс. вставок в секунду (примерно в 10 раз больше и около часа работы).

При этом с таким объемом данных я бы предложил:

  • дамп таблицы Oracle с использованием собственных инструментов базы данных Oracle, которые создают читаемый человеком контент (или читаемый компьютером, но вы должны иметь возможность его анализировать)

  • проанализируйте файл дампа, используя как можно более быстрые инструменты. Может grep быть, / sed / gawk / cut будет достаточно?

  • создайте целевой файл, совместимый с MySQL LOAD DATA INFILE (он очень настраиваемый)

  • Импортируйте файл в MySQL, используя вышеупомянутую команду

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

Это для начальной загрузки. После этого, вероятно, Spring Batch будет хорошим выбором. Если вы можете, попробуйте подключить свое приложение напрямую к обеим базам данных — опять же, это будет быстрее. С другой стороны, это может быть невозможно по соображениям безопасности.

Если вы хотите быть очень гибким и не привязывать себя к базам данных напрямую, предоставьте как ввод (Oracle), так и вывод (MySQL) за веб-сервисами (REST тоже подойдет). Интеграция с Spring вам очень поможет.

Комментарии:

1. В качестве альтернативы, используйте JDBC для извлечения записей из Oracle и записи их в формате «LOAD DATA INFILE» в файл или последовательность файлов. Вероятно, немного медленнее, чем при использовании встроенного инструментария oracle, но вы пропускаете шаг и по-прежнему используете скорость загрузки файла данных, что, вероятно, является более трудоемким фактором.

Ответ №2:

Вы можете использовать Scriptella для передачи данных между базами данных. Вот пример файла преобразования XML:

 <!DOCTYPE etl SYSTEM "http://scriptella.javaforge.com/dtd/etl.dtd">
<etl>
    <connection id="in" url="jdbc:oracle:thin:@localhost:1521:ORCL" 
              classpath="ojdbc14.jar" user="scott" password="tiger"/>

    <connection id="out" url="jdbc:mysql://localhost:3306/fromdb" 
              classpath="mysql-connector.jar" user="user" password="password"/>
    <!-- Copy all table rows from one to another database -->
    <query connection-id="in">
        SELECT * FROM Src_Table
        <!-- For each row executes insert -->  
        <script connection-id="out"> 
            INSERT INTO Dest_Table(ID, Name) VALUES (?id,?name)
        </script>
    </query>
  </etl>