如何使用JDBC有效地导出/导入数据库数据

问题描述 投票:0回答:3

我有一个JAVA应用程序,可以使用任何供应商的SQL数据库。现在我们测试了Vertica和PostgreSQL。我想从数据库中的一个表导出所有数据,然后在应用程序的另一个实例中导入它。 DB的大小非常大,因此有很多行。导出和导入过程必须在java代码中完成。

到目前为止我们尝试过的是:

  • 导出:我们通过JDBC读取整个表(select * from),然后将其转储到SQL文件中,并且需要所有INSERTS。
  • 导入:包含数千个INSERTS的文件通过JDBC在目标数据库中执行。

这不是一个有效的过程。首先,select * from部分因为它的大小而给我们带来了问题,其次,如果一个接一个地插入会给我们带来棘手问题(https://forum.vertica.com/discussion/235201/vjdbc-5065-error-too-many-ros-containers-exist-for-the-following-projections

这样做更有效的方法是什么?有没有可以帮助这个过程的工具,或者没有“优雅”的解决方案?

java postgresql jdbc vertica
3个回答
1
投票

为什么不在一个步骤中进行导出/导入,包括批处理(用于性能)和分块(以避免错误并提供检查点,以便在发生故障后从哪里开始)。

在大多数情况下,数据库支持具有许多值的INSERT查询,例如:

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
投票

我只能谈论PostgreSQL。

如果通过在语句上调用值大于0(可能为10000)的SELECT来使用服务器端游标,则setFetchSize的大小不是问题。

如果,INSERTS表现良好

  1. 你在一个交易中运行它们
  2. 你使用PreparedStatement作为INSERT

0
投票

Vertica中的每个插入都进入WOS(内存),并且来自WOS的定期数据被移动到ROS(磁盘)到一个容器中。每个节点每个投影只能有1024个ROS容器。一次做成千上万次INSERT对于Vertica来说绝不是一个好主意。执行此操作的最佳方法是将所有数据复制到文件中,然后使用COPY命令将文件批量加载到Vertica中。

这将为文件内容创建一个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

© www.soinside.com 2019 - 2024. All rights reserved.