目前,我正在开发一个Spring Boot应用程序,它周期性地尝试处理一个包含用户数据的文件,其中每一行包含userIddepartamentId并用|分隔,例如123534|13。那个文件将包含几百万条记录。
我的要求是将这些数据加载到mysql数据库中,以便:
如果已处理ID的用户存在,则不做任何事情。
如果用户不存在,则创建新用户
如果用户不在列表中,但存在于数据库中,请将其删除
如果数据库中不存在当前部门,请创建它
我做了一些优化,比如
缓存将离开以填充实体
通过JpaRepositorysaveAll方法批量收集用户进行保存
但是我仍然对数据库进行了太多的数据库调用,我正在检查用户是否存在,以便为每个记录创建保存实体。。。
我的实体相当简单:

@Entity
@Table(name = "departaments")
public class Departament{

    @Id
    @Column(name = "id")
    private Long id;

    @Column(name = "name")
    private String name;

以及:
@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @ManyToOne
    @JoinColumn(name = "departament_id")
    private Departament departament;

有人遇到过这样的问题吗?
是否可以进一步优化?
有什么好的处理模式吗?

最佳答案

这里有几件事:
对于用户来说,您的主要真实来源似乎是CSV文件。为什么不简单地截断并重新创建USER表呢?您可能会遇到一些问题(我知道在您的场景中引用完整性不是其中之一,或者是这样?),但您将免费获得用户删除(TBH我不太清楚您在当前设置中如何处理用户删除)。它会跑得更快with key checks disabled
在使用saveAll时,您是否真的看到了性能改进?这并不限制要执行的SELECT语句的数量
你确定你在正确的抽象层次上操作吗?也许您可以使用普通的JDBC而不是JPA。对于JPA,将涉及大量的缓存/映射,这会导致很大的开销。使用JDBC,您可以利用MySQL的INSERT IGNOREINSERT ... ON DUPLICATE KEY UPDATE语句来获得所需的内容
如果您选择上述任何一种方法,您可以尝试使用Spring Batch进行更多的声明性处理

10-04 14:10
查看更多