Skip to content
튜닝 연습파싱과 바인드 변수
PARSE-041

batch_size를 500으로 넣었는데 보정 요청 12,000건 업로드가 여전히 10초 가까이 걸린다

중급INSERT한빛유통586 / 700

상황 ​

한빛유통 정산팀은 매주 보정 요청 엑셀(약 12,000줄)을 관리 화면(Spring Boot, JPA)에 올린다. 화면은 줄마다 보정 요청 엔티티를 만들어 saveAll로 한꺼번에 저장한다. 업로드가 10초 가까이 걸려서 가끔 화면의 제한 시간(10초)을 넘긴다. 개발자는 블로그 글을 보고 hibernate.jdbc.batch_size=500을 넣었지만 9.8초가 9.6초가 됐을 뿐이다. "배치 크기를 넣었으니 500줄씩 묶여 나가야 하는데요?"

테이블과 인덱스 ​

  • T_STLM_ADJ_REQ 보정 요청(이 문제에서 쓰는 테이블): REQ_ID NUMBER GENERATED BY DEFAULT AS IDENTITY(PK) · STLM_SEQ · ADJ_AMT · REQ_DT · REQ_USER · 지금 31만 행, 주에 약 12,000행씩 는다 · 다른 프로그램은 이 테이블에 넣지 않는다
  • REQ_ID는 업무 의미가 없는 키다(화면과 보고서는 STLM_SEQ로 찾는다).
  • 관리 화면 서버와 DB의 왕복은 0.5ms다. 업로드는 한 트랜잭션으로 저장하고 끝에 한 번 커밋한다.

원본 SQL ​

sql
// AdjReq.java : 키는 DB의 IDENTITY 칸이 매긴다
@Entity
@Table(name = "T_STLM_ADJ_REQ")
public class AdjReq {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "REQ_ID")
    private Long reqId;
    private Long stlmSeq;
    private BigDecimal adjAmt;
    private LocalDateTime reqDt;
    private String reqUser;
}

# application.properties (지난주 추가)
spring.jpa.properties.hibernate.jdbc.batch_size=500

// AdjUploadService.java
@Transactional
public void upload(List<AdjRow> rows) {
    repo.saveAll(rows.stream().map(AdjReq::from).collect(toList()));   // 12,040건
}

실행계획 학습용 예시 ​

xplan
[업로드 한 번 (12,040줄) · 세션 통계 증가분]
  경과 시간                               9.6 초
  execute count                        12,046
  SQL*Net roundtrips to/from client    12,051
  session logical reads                49,812
  SQL*Net message from client          12,050번 · 6.9 초

[V$SQL]
  SQL_TEXT                                                                         EXECUTIONS   ROWS_PROCESSED
  insert into T_STLM_ADJ_REQ (adj_amt, req_dt, req_user, stlm_seq) values
    (:1 , :2 , :3 , :4 ) RETURNING REQ_ID INTO :5                                      12,040           12,040

[한 번 실행]  INSERT STATEMENT → LOAD TABLE CONVENTIONAL · Buffers 4 (테이블 블록, PK 인덱스 리프)

문제 ​

  1. batch_size를 넣었는데도 INSERT가 묶이지 않은 것을 위 숫자로 확인하고, 왜 묶이지 않았는지 설명하시오.
  2. 같은 데이터를 넣으면서 INSERT가 묶여 나가도록 고치시오. 고친 뒤의 실행 수와 왕복 수를 쓰고, 이 방법의 대가도 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자