SQLP 실기 기출

Kyojun Jin·2023년 3월 8일
0

SQLP

목록 보기
31/34

문제 참고

44회

1번

1. 필요없는 테이블이 있는가?

select *이므로 없다.

2. 조인 순서

board - article - member 순서로 cardinality 커지기 때문에, 그 순서로 조인하자.

3. 문제에서 최근 3일 또는 5일 전 게시글이 850여 건이라고 함

즉 게시글, article 테이블을 딱 850개 정도만 봐야 한다는 뜻이다. 그렇게 하려면 인덱스 스캔을 해야 한다.
board 에서 article로 조인할 때 brd_id로 index range scan을 할텐데, 이때 a.reg_dt 칼럼도 같이 쓰면 article 에서 850개 로우만 보게 될 것이다.

-- 인덱스 변경
ARTICLE_X01: BRD_ID, A.REG_DT

SELECT /*+ ORDERED USE_NL(A M) */ *
FROM
(SELECT 
B.BRD_ID,
B.BRD_NM,
A.ART_SN,
A.ART_TIL,
GET_TEXT(A.ART_CONT, 100) AS ART_CONT,
A.MBR_NO,
M.MBR_NM,
A.REG_DT
FROM BOARD B, ARTICLE A, MEMBER M
WHERE B.BRD_ID = :BRD_ID
AND A.BRD_ID = B.BRD_ID
AND A.MBR_NO = M.MBR_NO
AND A.REG_DT >= TRUNC(SYSDATE, -3)
ORDER BY A.REG_DT DESC
)
WHERE ROWNUM <= 5;

출처에서 작성자는 sort 연산을 skip 하기 위해 index_desc(a article_x01)을 추가해준다고 했는데, 경험 상 조인된 테이블에선 그렇게 해도 sort 연산을 생략할 수가 없다.

2번

1. 필요 없는 테이블이 있는가?

SELECT 절에선 A, B, C만 쓰고 있다.
MATERIAL 테이블은 필요하지 않다.

2. STAT_CD 조건 변경

STAT_CD NOT IN ('03', '04')라고 했는데, 어차피 03, 04가 아닌 건 01, 02 밖에 없다.
저걸 그대로 놔두면 full scan을 하게 된다.
STAT_CD IN ('01', '02') 로 바꿔준다.

3. 조인 순서

Order 테이블에서 부분범위처리가 많이 일어나기 때문에, order, company, ord_material 순으로 조인한다. order 다음엔 어느 순서로 하든 딱히 상관은 없다.

4. 인덱스 파티셔닝

ORD_MATERIAL 테이블이 1년 단위로 파티션 되어 있고, 해당 쿼리도 최근 1년을 자주 조회한다고 한다. ORDER에서 ORD_MATERIAL로 갈 때 ORD_NO를 사용하는데, ORD_MATERIAL 테이블에 ORD_NO, ORD_DT로 local non prefixed partition index를 생성해주자.
local 인 이유는 ORD_MATERIAL이 연 단위로 나뉘어 있는 이력성 데이터이기 때문이고, non prefixed인 이유는 파티션키는 ord_dt인데 선두는 ord_no이기 때문이다.
파티션 키 칼럼이 범위검색 조건으로 자주 사용된다면 Local prefixed보다 local nonprefixed가 유리하다.

--인덱스 추가
ORD_MATERIAL_X01: ORD_NO, ORD_DT (local nonprefiexed)

SELECT /*+ ordered index(B ORD_MATERIAL_X01) index(A ORDER_X01) */
A.ORD_NO, 
C.CMP_ID, 
C.CMP_NM, 
SUM(B.NUM_QTY) AS NUM_QTY, 
SUM(B.AMT_QTY) AS AMT_QTY, 
SUM(B.DC_QTY) AS DC_QTY
FROM ORDER A, ORD_MATERIAL B, COMPANY C
WHERE
A.STAT_CD IN ('01','02')
AND A.ORD_DT BETWEEN TO_DATE(:START_DT,'YYYY-MM-DD') AND TO_DATE(:END_DT,'YYYY-MM-DD')
AND A.ORD_NO = B.ORD_NO
AND A.CMP_ID = C.CMP_ID
GROUP BY A.ORD_NO, C.CMP_ID, C.CMP_NM;

0개의 댓글