Как эффективно экспортировать / импортировать данные базы данных с JDBC - PullRequest
0 голосов
/ 29 марта 2019

У меня есть приложение JAVA, которое может использовать базу данных SQL от любого поставщика. Прямо сейчас мы протестировали Vertica и PostgreSQL. Я хочу экспортировать все данные из одной таблицы в БД и затем импортировать их в другой экземпляр приложения. Размер БД довольно большой, поэтому там много строк. Процесс экспорта и импорта должен выполняться из кода Java.

То, что мы пробовали до сих пор:

  • Экспорт: мы читаем всю таблицу (select * from) через JDBC, а затем выгружаем ее в файл SQL со всеми необходимыми ВСТАВКАМИ.
  • Импорт: файл, содержащий эти тысячи INSERTS, выполняется в целевой базе данных через JDBC.

Это не эффективный процесс. Во-первых, часть select * from доставляет нам проблемы из-за ее размера, а во-вторых, выполнение большого количества операций, если вставка одна за другой создает проблемы в Vertica (https://forum.vertica.com/discussion/235201/vjdbc-5065-error-too-many-ros-containers-exist-for-the-following-projections)

Что может быть более эффективным способом сделать это? Существуют ли какие-либо инструменты, которые могут помочь в этом процессе, или нет «элегантного» решения?

Ответы [ 3 ]

1 голос
/ 29 марта 2019

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

В большинстве случаев базы данных поддерживают INSERT запросов со многими значениями, например ::100100

INSERT INTO table_a (col_a, col_b, ...) VALUES
(val_a, val_b, ...),
(val_a, val_b, ...),
(val_a, val_b, ...),
...

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

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

Для самих блоков вам действительно следует использовать LIMIT OFFSET .

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

0 голосов
/ 29 марта 2019

Каждая вставка в Vertica попадает в WOS (память), и периодически данные из WOS перемещаются в ROS (диск) в один контейнер.Вы можете иметь только 1024 контейнера ROS на проекцию на узел.Делать много тысяч вставок за раз - это никогда не хорошая идея для Vertica.Лучший способ сделать это - скопировать все эти данные в файл и выполнить массовую загрузку файла в Vertica с помощью команды COPY.

Это создаст один контейнер ROS для содержимого файла.В зависимости от того, сколько строк вы хотите скопировать, это будет во много раз (иногда даже в сотни раз) быстрее.

https://www.vertica.com/docs/9.2.x/HTML/Content/Authoring/SQLReferenceManual/Statements/COPY/COPY.htm

https://www.vertica.com/docs/9.2.x/HTML/Content/Authoring/ConnectingToVertica/ClientJDBC/UsingCOPYLOCALWithJDBC.htm

0 голосов
/ 29 марта 2019

Я могу говорить только о PostgreSQL.

Размер SELECT не является проблемой, если вы используете серверные курсоры, вызывая setFetchSize со значением больше 0 (возможно, 10000) взаявление.

INSERTS будет работать хорошо, если

  1. вы запустите их все в одной транзакции

  2. выиспользуйте PreparedStatement для INSERT

...