[JPA] 복합 외래키 사용시 insert 속도 개선

파워소동·2023년 3월 26일
0

JPA

목록 보기
1/4

Spring boot + JPA로 개발하던 중 약 100건 ~ 200건의 데이터를 한 번에 insert 하는 로직을 개발했는데 속도가 너무 느려서 개선을 해보았습니다.

우선 지금 내가 저장하고자 하는 테이블의 PK는 복합키입니다. 두 개의 컬럼을 복합키로 가지고 있는데, 하나는 자동 증가하는 sequence 컬럼이고 다른 하나는 다른 테이블의 PK입니다. 즉 복합키 중 하나의 키는 외래키입니다.

그래서 insert를 하기 전에 entity에 해당 외래키를 set해두고 save를 해야합니다.

예를들어서 아래코드와 같습니다.

ProductEntity productEntity = new ProductEntity();
productEntity.setProductMasterEntity(productMasterEntity);
productRepository.save(productEntity);

예시코드입니다. 실제로는 entity에 new를 쓰지도 set을 쓰지도 않습니다...

여튼.

JPA고수라면 다들 알겠지만
JPA는 save()를 하기 전에 Entity의 식별자값인 Id에 값이 있으면 SELECT 쿼리가 먼저 나갑니다. 그리고 그 SELECT 쿼리의 결과를 바탕으로 값이 있으면 UPDATE 쿼리를, 값이 없으면 INSERT 쿼리를 진행하게 됩니다.

근데 저의 경우에는 위에 작성했다싶이
Id, 즉 pk가 복합키 입니다. 복합키중 한 컬럼은 외래키라 save이전에 지정을 해주기 때문에 값이 무조건 있는 상황입니다!! 그래서 제 의도는 insert이지만 자꾸만 save하기 전에 select가 나가서 속도가 느려졌던 것입니다.

이런경우... 여러가지 해결방법이 있을 수 있습니다만 저는 엔티티에 Persistable 인터페이스를 구현해 해결했습니다.

@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Table(name = "TB_PRODUCT")
@TableGenerator(
        name = "generator",
        table = "sequences",
        pkColumnName = "seq",
        initialValue = 1,
		allocationSize = 100
)
@IdClass(ProductEntityId.class)
public class ProducEntity implements Persistable<ProductEntityId> {

    @Id
    @ManyToOne(fetch = FetchType.LAZY)
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JoinColumn(name = "PROD_MST_CD", nullable = false)
    @Comment("상품마스터")
    private ProductMasterEntity productMaster;

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "generator")
    @Column(name = "PROD_SEQ")
    @Comment("상품시퀀스")
    private Integer productSequence;

    /**
     * 컬럼 생략
     */

    @Override
    public ProductEntityId getId() {
        return new ProductEntityId(this.productMaster.getProductMasterSequence(), this.productSequence);
    }

    @Override
    public boolean isNew() {
        return this.productSequence == null;
    }
}

Persistable을 implements해서 getId(), isNew() 메서드를 구현하면 됩니다!!
getId()는 제 entity의 Id를 return 하도록 했고 isNew() 메서드는 자동 증가되는 시퀀스 컬럼값만 바라보게 설정 해주었습니다.

이렇게 설정하고 나니 제 의도대로 바로 insert 쿼리가 나가면서 속도가 많이 빨라졌습니다!

그럼 언젠가 JPA의 고수가 되는 그날까지!! 안녕~!!!

0개의 댓글