테마
본사 영업관리팀의 「매장 판매 이력」 화면은 매장과 기간을 고르면 일자별 판매 건수를 보여 준다. 매장 담당자들이 하루 수백 번 연다.
지난달 조민우가 구 POS 시절의 2021년 판매(CF10_ARC)도 같은 화면에서 보이도록 두 테이블을 합친 통합 뷰 V_SLE_HIST를 만들고, 화면이 그 뷰를 읽게 바꿨다. 처음 만든 뷰는 UNION ALL에서 ORA-01790으로 거부되어 한 줄을 고쳐 다시 만들었다. 그 뒤로 2023년 6월 한 달을 고르면 0.01초이던 화면이 0.09초가 되었다. 화면 SQL에는 함수도 형변환도 없다.
CF10_P 판매(파티션 복사본, 문제 설정): CF10 500,000행을 PARTITION BY RANGE (SLE_DT) 월별 24칸(P202201 ~ P202312)과 빈 PMAX로 나눠 CTAS로 지었다. 칸 하나는 약 20,800행이고 FULL로 약 192블록, 24칸 전체는 약 4,610블록이다. P202306은 18번째 칸이다. SLE_DT는 VARCHAR2(8) '20230615'이다.CF10_ARC 판매 보관(문제 설정): 구 POS에서 옮긴 2021년 판매 249,600행 · 2,290블록. 컬럼은 CF10과 같지만 SLE_DT가 NUMBER(8) 20210615이다. 앞으로 DML이 없다. 인덱스 CF10_ARC_X01 (SLE_DT): BLEVEL 1.CF10_P에는 이 조회에 쓸 인덱스가 없다. 통계는 최신이다.SLE_DT가 숫자라서 기간을 숫자(:v_from = 20230601, :v_to = 20230630)로 넘긴다.-- 통합 판매 이력 뷰 (ORA-01790 이 난 뒤 고쳐 만든 판)
CREATE OR REPLACE VIEW V_SLE_HIST AS
SELECT SLE_NO, TO_NUMBER(SLE_DT) AS SLE_DT, SLE_HMS, SHP_NO
FROM CF10_P
UNION ALL
SELECT SLE_NO, SLE_DT, SLE_HMS, SHP_NO
FROM CF10_ARC;
-- 「매장 판매 이력」 화면
SELECT SLE_DT, COUNT(*) AS sle_cnt
FROM V_SLE_HIST
WHERE SHP_NO = :v_shp
AND SLE_DT BETWEEN :v_from AND :v_to
GROUP BY SLE_DT
ORDER BY SLE_DT
-------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Pstart | Pstop |
-------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 30 | 00:00:00.09 | 4612 | | |
| 1 | SORT GROUP BY | | 1 | 85 | 30 | 00:00:00.09 | 4612 | | |
| 2 | VIEW | V_SLE_HIST | 1 | 312 | 3468 | 00:00:00.09 | 4612 | | |
| 3 | UNION-ALL | | 1 | | 3468 | 00:00:00.09 | 4612 | | |
|* 4 | FILTER | | 1 | | 3468 | 00:00:00.09 | 4610 | | |
| 5 | PARTITION RANGE ALL | | 1 | 208 | 3468 | 00:00:00.09 | 4610 | 1 | 25 |
|* 6 | TABLE ACCESS FULL | CF10_P | 24 | 208 | 3468 | 00:00:00.08 | 4610 | 1 | 25 |
|* 7 | FILTER | | 1 | | 0 | 00:00:00.01 | 2 | | |
|* 8 | TABLE ACCESS BY INDEX ROWID BATCHED | CF10_ARC | 1 | 104 | 0 | 00:00:00.01 | 2 | | |
|* 9 | INDEX RANGE SCAN | CF10_ARC_X01 | 1 | 624 | 0 | 00:00:00.01 | 2 | | |
-------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - filter(:V_FROM<=:V_TO)
6 - filter(("SHP_NO"=:V_SHP AND TO_NUMBER("SLE_DT")>=:V_FROM AND TO_NUMBER("SLE_DT")<=:V_TO))
7 - filter(:V_FROM<=:V_TO)
8 - filter("SHP_NO"=:V_SHP)
9 - access("SLE_DT">=:V_FROM AND "SLE_DT"<=:V_TO)
[바인드 — V$SQL_BIND_CAPTURE]
NAME DATATYPE_STRING VALUE_STRING
:V_FROM NUMBER 20230601
:V_TO NUMBER 20230630
CF10_P의 칸을 전부 여는 까닭을 Predicate Information과 뷰 정의로 설명하시오. 뷰를 만든 사람이 왜 그렇게 고쳤는지도 쓰시오.