테마
운영 상황판 첫 화면의 「이번 달 주문 현황」 타일은 이번 달 전체 주문 수, 완료 주문 수와 금액, 대기 주문 수, 취소 주문 수를 보여 주고, 업무 시간(09 ~ 21시)에는 1분마다 새로 고친다. 한 번에 0.5초라 아무도 신경 쓰지 않았는데, 지난주 AWR의 SQL ordered by Gets에서 이 SQL이 1위로 나왔다(하루 720번, 약 2,100만 블록). 아래는 2024년 6월을 조회했을 때의 실행계획이다.
T_ORD_BIG: 1,000,000행 · 5,826블록 · 이 문제에서는 인덱스가 없다 · ORD_DT DATE(전부 자정) · ORD_ST COMPLETE 90% · PENDING 8% · CANCEL 2%:v_from, :v_to)로 넘긴다SELECT (SELECT COUNT(*) FROM T_ORD_BIG
WHERE ORD_DT >= :v_from AND ORD_DT < :v_to) AS all_cnt,
(SELECT COUNT(*) FROM T_ORD_BIG
WHERE ORD_DT >= :v_from AND ORD_DT < :v_to AND ORD_ST = 'COMPLETE') AS cmpl_cnt,
(SELECT SUM(ORD_AMT) FROM T_ORD_BIG
WHERE ORD_DT >= :v_from AND ORD_DT < :v_to AND ORD_ST = 'COMPLETE') AS cmpl_amt,
(SELECT COUNT(*) FROM T_ORD_BIG
WHERE ORD_DT >= :v_from AND ORD_DT < :v_to AND ORD_ST = 'PENDING') AS pend_cnt,
(SELECT COUNT(*) FROM T_ORD_BIG
WHERE ORD_DT >= :v_from AND ORD_DT < :v_to AND ORD_ST = 'CANCEL') AS cncl_cnt
FROM DUAL
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 | 00:00:00.52 | 29130 |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 | 00:00:00.11 | 5826 |
|* 2 | TABLE ACCESS FULL | T_ORD_BIG | 1 | 27266 | 27390 | 00:00:00.11 | 5826 |
| 3 | SORT AGGREGATE | | 1 | 1 | 1 | 00:00:00.10 | 5826 |
|* 4 | TABLE ACCESS FULL | T_ORD_BIG | 1 | 24539 | 24651 | 00:00:00.10 | 5826 |
| 5 | SORT AGGREGATE | | 1 | 1 | 1 | 00:00:00.10 | 5826 |
|* 6 | TABLE ACCESS FULL | T_ORD_BIG | 1 | 24539 | 24651 | 00:00:00.10 | 5826 |
| 7 | SORT AGGREGATE | | 1 | 1 | 1 | 00:00:00.10 | 5826 |
|* 8 | TABLE ACCESS FULL | T_ORD_BIG | 1 | 2181 | 2191 | 00:00:00.10 | 5826 |
| 9 | SORT AGGREGATE | | 1 | 1 | 1 | 00:00:00.10 | 5826 |
|* 10 | TABLE ACCESS FULL | T_ORD_BIG | 1 | 545 | 548 | 00:00:00.10 | 5826 |
| 11 | FAST DUAL | | 1 | 1 | 1 | 00:00:00.01 | 0 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(("ORD_DT">=:V_FROM AND "ORD_DT"<:V_TO))
4 - filter(("ORD_ST"='COMPLETE' AND "ORD_DT">=:V_FROM AND "ORD_DT"<:V_TO))
6 - filter(("ORD_ST"='COMPLETE' AND "ORD_DT">=:V_FROM AND "ORD_DT"<:V_TO))
8 - filter(("ORD_ST"='PENDING' AND "ORD_DT">=:V_FROM AND "ORD_DT"<:V_TO))
10 - filter(("ORD_ST"='CANCEL' AND "ORD_DT">=:V_FROM AND "ORD_DT"<:V_TO))
T_ORD_BIG을 한 번만 읽도록 SQL을 고치시오. 건수를 셀 때 CASE의 ELSE를 어떻게 써야 하는지도 설명하시오.