使用springboot应用程序进行数据迁移需要太多时间

时间:2020-03-02 13:52:10

标签: spring spring-boot spring-data-jpa database-migration

我已经使用springboot在Java中创建了一个命令行应用程序,该程序将数据从oracle数据库迁移到mysql数据库

我正在遵循服务等级

@Service
public class MyService{

    @Autowired
    public OracleUserRepository oracleUserRepository;

    @Autowired
    public OracleUserAddressRepository oracleUserAddressRepository;

    @Autowired
    public OracleUserDetailsRepository oracleUserDetailsRepository;

    @Autowired
    public MysqlUserRepository mysqlUserRepository;

    @Autowired
    public MysqlUserAddressRepository mysqlUserAddressRepository;

    @Autowired
    public MysqlUserDetailsRepository mysqlUserDetailsRepository;

    public void migrateData(){
        List<OracleUserEntity> oracelUserEntities=oracleUserRepository.findAll();
        for (OracleUserEntiy oracleUserEntity: oracleUserEntities){
            migrateEntity(oracleUserEntity);
        }
    }

    @Transactional("mysqlTransactionManager")
    public void migrateEntity(OracleUserEntity oracleUserEntity){

        OracleUserAddressEntity oracleUserAddressEntity=getAddressEntity(oracleUserEntity);
        OracleUserDetailsEntity oracleUserDetailsEntity=getDetailsEntity(oracleDetaislEntity);


        MysqlUserEntity mysqlUserEntity=convertToMysqlUserEntity(oracleUserEntity);
        mysqlUserRepository.save(mysqlUserEntity);

        MysqlUserAddressEntity mysqlUserAddressEntity=convertToMysqlAddressEntity(oracleUserAddressEntity);
        mysqlUserAddressRepository.save(mysqlUserAddressEntity);

        MysqlUserDetailsEntity mysqlUSerDetailsEntity=convertToMysqlUserDetailsEntity(oracleUserDetailsEntity);
        mysqlUserDetailsRepository.save(mysqlUserAddressEntity);
    }
}

我使用 transactional 保存每个用户,因为如果userAddressEntity或userDetailsEntity中的任何一个保存失败,我想回滚

我在oracle数据库中大约有 70K 个条目。 oracleUserRepository.findAll()方法仅花费了大约 40分钟来加载所有实体并将实体保存到mysql DB会花费更多时间。

这是正确的方法吗?无论如何,有什么可以提高性能的吗?

3 个答案:

答案 0 :(得分:0)

JPA确实具有批处理功能以提高性能。

但是,这种用例似乎是脚本解决方案的理想选择,因此可以完全控制SQL语句和事务。

答案 1 :(得分:0)

70K应该没问题。尝试读取每一行并插入到mysql中,而不是将所有内容都插入内存中。当您执行每行方法时,请删除Transactional,这可能会导致速度变慢。如果失败,请记录异常并在数据发布并重新运行时重试或修复数据。

答案 2 :(得分:0)

这不会很有效,但是.findall方法加载70k条记录应该不需要40分钟...当然,假设您发现所有内容只是在尝试返回每一行,而不会被重载具有限制选择,并且原始表很大,并且您的选择位于非索引列上。您确定您的Java进程或Oracle Server上没有资源约束吗?您的JVM堆足够大吗?

如果您使用sqlplus连接到数据库,然后运行select从用户表中查找所有内容,那么需要多长时间?如果那也很慢,那么您在数据库级别上正在进行某种资源/争用/锁定...如果响应迅速,但是您的程序花了40分钟才能得到结果,则需要检查JVM ..是否受资源限制?等等