我有一个JAVA应用程序,可以使用任何供应商的SQL数据库。现在我们测试了Vertica和PostgreSQL。我想从数据库中的一个表导出所有数据,然后在应用程序的另一个实例中导入它。 DB的大小非常大,因此有很多行。导出和导入过程必须在java代码中完成。
到目前为止我们尝试过的是:
select * from
),然后将其转储到SQL文件中,并且需要所有INSERTS。这不是一个有效的过程。首先,select * from
部分因为它的大小而给我们带来了问题,其次,如果一个接一个地插入会给我们带来棘手问题(https://forum.vertica.com/discussion/235201/vjdbc-5065-error-too-many-ros-containers-exist-for-the-following-projections)
这样做更有效的方法是什么?有没有可以帮助这个过程的工具,或者没有“优雅”的解决方案?
为什么不在一个步骤中进行导出/导入,包括批处理(用于性能)和分块(以避免错误并提供检查点,以便在发生故障后从哪里开始)。
在大多数情况下,数据库支持具有许多值的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 。
这样,您可以随时重复任何块,每个块本身都是原子的,它应该比单行语句执行得更好。
我只能谈论PostgreSQL。
如果通过在语句上调用值大于0(可能为10000)的SELECT
来使用服务器端游标,则setFetchSize
的大小不是问题。
如果,INSERTS
表现良好
PreparedStatement
作为INSERT
Vertica中的每个插入都进入WOS(内存),并且来自WOS的定期数据被移动到ROS(磁盘)到一个容器中。每个节点每个投影只能有1024个ROS容器。一次做成千上万次INSERT对于Vertica来说绝不是一个好主意。执行此操作的最佳方法是将所有数据复制到文件中,然后使用COPY
命令将文件批量加载到Vertica中。
这将为文件内容创建一个ROS容器。根据您要复制的行数,它将更快(有时甚至数百倍)。