Skip to content
튜닝 연습서브쿼리와 쿼리 변환
SUBQ-039

운영본과 보관본의 MINUS 대사가 0행으로 끝났는데, 한 문장에 20초와 TEMP 400MB가 든다

실전SELECT버거274 / 700

상황 ​

14화의 파티션 전환을 앞두고 박팀장이 주문했다. "운영본 ORD_RANDOM이 이관 전 보관본 ORD와 한 줄도 다르지 않다는 것부터 보여라." 조민우가 MINUS 대사 두 문장을 낮 시간에 돌렸다. 두 문장 다 0행이었고 건수도 1,000,000 = 1,000,000이었다. 대신 한 문장에 20초씩 걸렸고, 그동안 TEMP를 400MB씩 써서 다른 배치가 TEMP 부족 경고를 받았다. 오과장은 서버를 바꿀 때 ORD_RANDOM 적재가 중간에 한 번 끊겼다가 다시 돌았다고 기억한다. 그런데 ORD_RANDOM에는 PK가 없다.

테이블과 인덱스 ​

  • ORD(이관 전 보관본): 1,000,000행 · 22,422블록 · ORD_PK (ORD_NO)
  • ORD_RANDOM(운영본): 1,000,000행 · 22,414블록 · PK 없음(인덱스는 ORD_RANDOM_X01 (ORD_DT, ORD_HMS)뿐) · 서버 교체 때 ORDER BY 없이 다시 적재
  • 두 표의 컬럼 9개: ORD_NO, ORD_DT, ORD_HMS, SHOP_NO, UPPER2, UPPER_CASE, LOWER_CASE, ALPHABET(100자), ALPHABET_NUMERIC(100자) · 한 행 약 190바이트 · ORD_PK 말고는 NOT NULL 제약이 없다
  • PGA는 자동 관리(정렬이나 해시 하나에 약 20MB까지 메모리) · 통계 최신

원본 SQL ​

sql
-- ① 보관본에만 있는 행
SELECT ORD_NO, ORD_DT, ORD_HMS, SHOP_NO, UPPER2, UPPER_CASE, LOWER_CASE, ALPHABET, ALPHABET_NUMERIC
  FROM ORD
MINUS
SELECT ORD_NO, ORD_DT, ORD_HMS, SHOP_NO, UPPER2, UPPER_CASE, LOWER_CASE, ALPHABET, ALPHABET_NUMERIC
  FROM ORD_RANDOM;

-- ② 운영본에만 있는 행
SELECT ORD_NO, ORD_DT, ORD_HMS, SHOP_NO, UPPER2, UPPER_CASE, LOWER_CASE, ALPHABET, ALPHABET_NUMERIC
  FROM ORD_RANDOM
MINUS
SELECT ORD_NO, ORD_DT, ORD_HMS, SHOP_NO, UPPER2, UPPER_CASE, LOWER_CASE, ALPHABET, ALPHABET_NUMERIC
  FROM ORD;

실행계획 학습용 예시 ​

xplan
[① — ② 도 같은 모양 · 19.84초 · 44,836블록 · TEMP 약 400MB]
-----------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation           | Name       | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads | Writes | Used-Mem | Used-Tmp |
-----------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |            |      1 |        |      0 |00:00:19.84 |   44836 | 51210 |  51210 |          |          |
|   1 |  MINUS              |            |      1 |        |      0 |00:00:19.84 |   44836 | 51210 |  51210 |          |          |
|   2 |   SORT UNIQUE       |            |      1 |   1000K|   1000K|00:00:09.71 |   22422 | 25605 |  25605 |   21M (1)|   201M   |
|   3 |    TABLE ACCESS FULL| ORD        |      1 |   1000K|   1000K|00:00:00.31 |   22422 |     0 |      0 |          |          |
|   4 |   SORT UNIQUE       |            |      1 |   1000K|   1000K|00:00:09.69 |   22414 | 25605 |  25605 |   21M (1)|   201M   |
|   5 |    TABLE ACCESS FULL| ORD_RANDOM |      1 |   1000K|   1000K|00:00:00.30 |   22414 |     0 |      0 |          |          |
-----------------------------------------------------------------------------------------------------------------------------------

[① 결과 0행 · ② 결과 0행 · 두 문장 합계 89,672블록 · 약 40초]

문제 ​

  1. MINUS 양방향 0행과 건수 일치만으로는 두 표가 같다고 단정할 수 없는 경우를 MINUS의 뜻으로 설명하시오. NULL이 든 컬럼을 MINUS가 어떻게 비교하는지도 설명하시오.
  2. 두 표를 한 번씩만 읽고 중복과 내용 차이를 함께 잡는 대사 SQL을 작성하고, 원래 대사와 일량(Buffers, TEMP, 시간)을 비교하시오.
  3. 키(ORD_NO)로 양쪽에 NOT EXISTS를 돌리자는 안과 FULL OUTER JOIN으로 컬럼을 비교하자는 안의 장단점을 서술하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자