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

실사 보정 8,412줄을 반영하는 데 7.9초, 하드 파싱은 두 번뿐이다

기초UPDATE유통581 / 700

상황 ​

유통 본사 물류팀은 매달 말 물류센터의 실사 결과 파일(입출고번호, 상품번호, 실사 수량)로 입출고상품 수량을 보정한다. 2011년에 만든 Java 프로그램이 파일 한 줄마다 UPDATE를 한 번씩 보낸다. 이번 달 8,412줄에 7.9초가 걸렸다. DBA가 세션 통계를 보내며 말했다. "바인드 변수는 잘 쓰고 있어요. 그런데 parse count가 실행 수만큼 올라갑니다."

테이블과 인덱스 ​

  • CF15 입출고상품: 51,497행 · 349블록 · PK (INOUT_NO, ITM_NO) · INOUT_NO는 VARCHAR2(15), ITM_NO는 NUMBER다
  • 한 줄을 고치는 데 PK로 3블록 남짓을 읽는다.
  • 배치 서버와 DB 서버의 왕복은 0.6ms다. JDBC 문장 캐시는 쓰지 않는다. session_cached_cursors = 50

원본 SQL ​

sql
// StockAdjust.java (2011) : 실사 파일 한 줄마다 문장을 준비하고, 실행하고, 닫는다
conn.setAutoCommit(false);
for (String[] f : lines) {                        // 8,412줄
    PreparedStatement ps = conn.prepareStatement(
        "UPDATE CF15 SET INOUT_QTY = ? WHERE INOUT_NO = ? AND ITM_NO = ?");
    ps.setInt(1, Integer.parseInt(f[2]));
    ps.setString(2, f[0]);
    ps.setInt(3, Integer.parseInt(f[1]));
    ps.executeUpdate();
    ps.close();
}
conn.commit();

실행계획 학습용 예시 ​

xplan
[세션 통계 증가분 · 8,412줄 한 번]
  경과 시간                              7.9 초
  execute count                          8,431
  parse count (total)                    8,433
  parse count (hard)                         2
  session cursor cache hits              8,409
  opened cursors cumulative              8,440
  SQL*Net roundtrips to/from client      8,418
  session logical reads                 33,890
  CPU used by this session                 214 cs

[V$SQL · UPDATE CF15 SET INOUT_QTY = :1 WHERE INOUT_NO = :2 AND ITM_NO = :3]
  PARSE_CALLS 8,412 · EXECUTIONS 8,412 · ROWS_PROCESSED 8,412 · BUFFER_GETS 33,648

[V$SESSION_EVENT · 같은 세션]
  SQL*Net message from client            8,417번 · 5.3 초
  log file sync                              1번 · 0.004 초

[한 번 실행의 계획]
---------------------------------------------------------------------------------
| Id  | Operation          | Name    | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
---------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT   |         |      1 |        |      0 |00:00:00.01 |       4 |
|   1 |  UPDATE            | CF15    |      1 |        |      0 |00:00:00.01 |       4 |
|*  2 |   INDEX UNIQUE SCAN| CF15_PK |      1 |      1 |      1 |00:00:00.01 |       2 |
---------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("INOUT_NO"=:2 AND "ITM_NO"=:3)

문제 ​

  1. 하드 파싱은 두 번뿐인데 parse count (total)가 실행 수만큼 오른 이유를 코드와 V$SQL로 설명하시오. 7.9초가 어디에 쓰였는지도 쓰시오.
  2. 결과가 바뀌지 않게 프로그램을 고치고, 고친 뒤 파스 호출과 왕복이 몇 번이 되는지 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자