프린트 하기

OS환경 : Oracle Linux 7.6 (64bit)

 

DB 환경 : Oracle Database 19.11.0.0

 

방법 : sqlp 실기튜닝실습 17-1 PUSH PREDICATE 문제 devDo 

devDo님의 블로그를 참고하여 테이블 생성 후 실습함

sqlp 실기 준비 스터디를 진행하면서 나온 스터디원의 답안과 모법답안을 작성함

* 문제 쿼리는 문제와 동일한 실행계획을 표현하기위해 힌트를 사용해서 고정함

* 쿼리 실행 유저는 IMSI 유저를 사용함(다른 유저명으로 생성해서 사용해도 문제없음)

* 본문 샘플데이터의 분포, DB 버전이 문제와 동일하지 않기 때문에 문제와 답안의 성능(결과)가 devDo님 결과와 다를수있음

 

 

문제) 비효율을 찾아 튜닝을 하시오.

전제조건

[고객(emp_p)] 테이블 70,000건, 고객코드(empcd) 'z0005' 은 0.5% 분포도를 가짐
[주문(order_p)] 테이블은 1,500,000건

 

 

인덱스구성

1
2
idx_emp_p_01 : empcd
idx_order_p_01 empid + orderdt

 

 

SQL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
SQL>
select /*+ gather_plan_statistics leading(a b) use_nl(b) index(b emp_p_pk) no_merge(a) */ 
a.empid, cnt 총주문횟수, price 총주문금액, qty 총주문량, dt 최종주문일자, b.empnm, b.addr, b.phone
from
(
 select /*+ full(order_p) */ empid, count(*) cnt, sum(orderpric) price, sum(orderqty) qty, max(orderdt) dt
 from order_p
 where orderdt between '20140901' and '20140903'
 group by empid
) a, emp_p b
where a.empid = b.empid
and b.empcd = 'z0005';
 
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULLNULL'ADVANCED ALLSTATS LAST'));
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation             | Name    | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time    | Buffers | Reads  |  OMem |  1Mem | Used-Mem |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |        |      1 |      |      |  2002 (100)|      |     3 |00:00:00.08 |    6605 |   5169 |       |       |      |
|   1 |  NESTED LOOPS             |        |      1 |    1 |    94 |  2002   (2)| 00:00:01 |     3 |00:00:00.08 |    6605 |   5169 |       |       |      |
|   2 |   NESTED LOOPS             |        |      1 |  11590 |    94 |  2002   (2)| 00:00:01 |    621 |00:00:00.08 |    5984 |   4850 |       |       |      |
|   3 |    VIEW              |        |      1 |  11590 |   656K|  1456   (2)| 00:00:01 |  12607 |00:00:00.09 |    5291 |   4850 |       |       |      |
|   4 |     HASH GROUP BY         |        |      1 |  11590 |   226K|  1456   (2)| 00:00:01 |  12607 |00:00:00.08 |    5291 |   4850 |  2132K|  1219K| 2899K (0)|
|*  5 |      TABLE ACCESS FULL         | ORDER_P    |      1 |  11591 |   226K|  1454   (2)| 00:00:01 |  12607 |00:00:00.07 |    5291 |   4850 |       |       |      |
|*  6 |    INDEX UNIQUE SCAN         | EMP_P_PK |  12607 |    1 |      |    0   (0)|      |    621 |00:00:00.01 |     693 |     0 |       |       |      |
|*  7 |   TABLE ACCESS BY INDEX ROWID| EMP_P    |    621 |    1 |    36 |    1   (0)| 00:00:01 |     3 |00:00:00.01 |     621 |    319 |       |       |      |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   5 - filter(("ORDERDT">='20140901' AND "ORDERDT"<='20140903'))
   6 - access("A"."EMPID"="B"."EMPID")
   7 - filter("B"."EMPCD"='z0005')

 

 

샘플 데이터 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
-------샘플데이터 생성 시작-------
-- 테이블 생성
drop table emp_p purge;
drop table sample_p purge;
drop table order_p;
create table sample_p (empid number, empnm varchar2(5), addr varchar2(10), phone varchar2(13), empcd varchar2(5)) nologging;
create table order_p (empid number, orderdt varchar2(8), orderpric number, orderqty number) nologging;
 
-- 데이터 생성(1/10)
DECLARE
TYPE tbl_ins IS TABLE OF sample_p%ROWTYPE INDEX BY BINARY_INTEGER;
w_ins tbl_ins;
BEGIN
FOR i IN 1..69650 LOOP 
   w_ins(i).empid := i;
   w_ins(i).empnm := dbms_random.string('x',5);
   w_ins(i).addr := 'addr';
   w_ins(i).phone := '010-'||ceil(dbms_random.value(10009999))||'-'||ceil(dbms_random.value(10009999));
   w_ins(i).empcd := dbms_random.string('x',1)||ceil(dbms_random.value(10009999));
END LOOP;
FORALL i in 1..69650 INSERT INTO sample_p VALUES w_ins(i);
   COMMIT;
END;
/
 
DECLARE
TYPE tbl_ins IS TABLE OF sample_p%ROWTYPE INDEX BY BINARY_INTEGER;
w_ins tbl_ins;
BEGIN
FOR i IN 69651..70000 LOOP 
   w_ins(i).empid := i;
   w_ins(i).empnm := dbms_random.string('x',5);
   w_ins(i).addr := 'addr';
   w_ins(i).phone := '010-'||ceil(dbms_random.value(10009999))||'-'||ceil(dbms_random.value(10009999));
   w_ins(i).empcd := 'z0005';
END LOOP;
FORALL i in 69651..70000 INSERT INTO sample_p VALUES w_ins(i);
   COMMIT;
END;
/
 
create table emp_p nologging as select * from sample_p order by dbms_random.random;
 
DECLARE
TYPE tbl_ins IS TABLE OF order_p%ROWTYPE INDEX BY BINARY_INTEGER;
w_ins tbl_ins;
BEGIN
FOR i IN 1..1500000 LOOP 
   w_ins(i).empid := i;
   w_ins(i).orderdt := '2014'|| to_char(round(dbms_random.value(1,12)) , 'FM09')  || to_char( round(dbms_random.value(1,28)) , 'FM09');
   w_ins(i).orderpric := ceil(dbms_random.value(110))*1000;
   w_ins(i).orderqty := ceil(dbms_random.value(110));
END LOOP;
FORALL i in 1..1500000 INSERT INTO order_p VALUES w_ins(i);
   COMMIT;
END;
/
 
alter table emp_p logging;
alter table order_p logging;
 
drop index emp_p_pk;
drop index emp_p_ix01;
drop index order_p_ix01;
create unique index emp_p_pk on emp_p(empid);
create index emp_p_ix01 on emp_p(empcd);
create index order_p_ix01 on order_p(empid, orderdt);
 
conn / as sysdba
select table_name, segment_created, last_analyzed from dba_tables where table_name in ('EMP_P','ORDER_P');
exec dbms_stats.gather_table_stats('IMSI''emp_p'cascade=>TRUE);
exec dbms_stats.gather_table_stats('IMSI''order_p'cascade=>TRUE);
select table_name, segment_created, last_analyzed from dba_tables where table_name in ('EMP_P','ORDER_P');
conn imsi/imsi

 

 

스터디원 답안

P님 답안

- 문제점 파악
order_p 테이블이 건수가 많지안 full scan 함
emp_p 테이블의 empcd='z0005'가 분포도가 0.5%인데 이 컬럼이 있는 인덱스로 사용하지 않고 empid 유니크 인덱스를 사용함
- 개선 방안
emp_p 테이블에서 empcd로 적은양을 찾고 empid 까지 인덱스에 포함
후행 테이블에는 조인키인 empid를 먼저 오게하고 orderdt가 오게끔 생성되어있는 인덱스로 이용하여 성능에 유리하게끔 작성
- 쿼리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
SQL>
drop index emp_p_ix02;
create index emp_p_ix02 on emp_p(empcd, empid);
select /*+ gather_plan_statistics leading(b a) use_nl(a) index(b emp_p_ix02) merge(a) */ 
a.empid, cnt 총주문횟수, price 총주문금액, qty 총주문량, dt 최종주문일자, b.empnm, b.addr, b.phone
from
(
 select /*+ order_p(index order_p_ix01) */ empid, count(*) cnt, sum(orderpric) price, sum(orderqty) qty, max(orderdt) dt
 from order_p
 where orderdt between '20140901' and '20140903'
 group by empid
) a, emp_p b
where a.empid = b.empid
and b.empcd = 'z0005';
 
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULLNULL'ADVANCED ALLSTATS LAST'));
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name          | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time    | A-Rows |   A-Time   | Buffers | Reads  |  OMem |  1Mem | Used-Mem |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |          |      1 |    |    |     8 (100)|        |      3 |00:00:00.01 |     381 |      6 |   |     |        |
|   1 |  HASH GROUP BY                   |          |      1 |      1 |    56 |     8  (13)| 00:00:01 |      3 |00:00:00.01 |     381 |      6 |   836K|   836K|  789K (0)|
|   2 |   NESTED LOOPS                   |          |      1 |      1 |    56 |     7   (0)| 00:00:01 |      3 |00:00:00.01 |     381 |      6 |   |     |        |
|   3 |    NESTED LOOPS                |          |      1 |      1 |    56 |     7   (0)| 00:00:01 |      3 |00:00:00.01 |     380 |      6 |   |     |        |
|   4 |     TABLE ACCESS BY INDEX ROWID BATCHED| EMP_P          |      1 |      1 |    36 |     4   (0)| 00:00:01 |    350 |00:00:00.01 |     353 |      2 |   |     |        |
|*  5 |      INDEX RANGE SCAN               | EMP_P_IX02   |      1 |      1 |    |     2   (0)| 00:00:01 |    350 |00:00:00.01 |       3 |      2 |   |     |        |
|*  6 |     INDEX RANGE SCAN               | ORDER_P_IX01 |    350 |      1 |    |     2   (0)| 00:00:01 |      3 |00:00:00.01 |      27 |      4 |   |     |        |
|   7 |    TABLE ACCESS BY INDEX ROWID           | ORDER_P      |      3 |      1 |    20 |     3   (0)| 00:00:01 |      3 |00:00:00.01 |       1 |      0 |   |     |        |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   5 - access("B"."EMPCD"='z0005')
   6 - access("EMPID"="B"."EMPID" AND "ORDERDT">='20140901' AND "ORDERDT"<='20140903')

 

 

J님 답안1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
SQL>
drop index emp_p_ix02;
select /*+ gather_plan_statistics leading(b) index (b emp_p_ix01) */ a.empid, cnt, price, qty, dt, b.empnm, b.addr, b.phone
from (
    select /*+ no_merge push_pred index (p order_p_ix01) */
        empid, count(*) cnt, sum(orderpric) price, sum(orderqty) qty, max(orderdt) dt
    from order_p p
    where orderdt between '20140901' and '20140903'
    group by empid
) a, emp_p b
where a.empid = b.empid
and b.empcd = 'z0005';
 
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULLNULL'ADVANCED ALLSTATS LAST'));
--------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                | Name           | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time     | A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |           |      1 |     |     |     7 (100)|      |    3 |00:00:00.01 |     923 |
|   1 |  NESTED LOOPS                |           |      1 |      1 |    81 |     7   (0)| 00:00:01 |    3 |00:00:00.01 |     923 |
|   2 |   TABLE ACCESS BY INDEX ROWID BATCHED    | EMP_P        |      1 |      1 |    36 |     3   (0)| 00:00:01 |    350 |00:00:00.01 |     235 |
|*  3 |    INDEX RANGE SCAN            | EMP_P_IX01   |      1 |      1 |     |     1   (0)| 00:00:01 |    350 |00:00:00.01 |       3 |
|   4 |   VIEW PUSHED PREDICATE         |           |    350 |      1 |    45 |     4   (0)| 00:00:01 |    3 |00:00:00.01 |     688 |
|*  5 |    FILTER                |           |    350 |     |     |          |      |    3 |00:00:00.01 |     688 |
|   6 |     SORT AGGREGATE            |           |    350 |      1 |    20 |          |      |    350 |00:00:00.01 |     688 |
|   7 |      TABLE ACCESS BY INDEX ROWID BATCHED| ORDER_P      |    350 |      1 |    20 |     4   (0)| 00:00:01 |    3 |00:00:00.01 |     688 |
|*  8 |       INDEX RANGE SCAN            | ORDER_P_IX01 |    350 |      1 |     |     3   (0)| 00:00:01 |    3 |00:00:00.01 |     686 |
--------------------------------------------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   3 - access("B"."EMPCD"='z0005')
   5 - filter(COUNT(*)>0)
   8 - access("EMPID"="B"."EMPID" AND "ORDERDT">='20140901' AND "ORDERDT"<='20140903')

 

 

J님 답안2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
SQL>
drop index emp_p_ix02;
select /*+ gather_plan_statistics leading(b) index (b emp_p_ix01) */ a.empid, cnt, price, qty, dt, b.empnm, b.addr, b.phone
from (
    select /*+ index (p order_p_ix01) */
        empid, count(*) cnt, sum(orderpric) price, sum(orderqty) qty, max(orderdt) dt
    from order_p p
    where orderdt between '20140901' and '20140903'
    group by empid
) a, emp_p b
where a.empid = b.empid
and b.empcd = 'z0005';
 
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULLNULL'ADVANCED ALLSTATS LAST'));
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name          | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time    | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |          |      1 |    |    |     7 (100)|        |      3 |00:00:00.01 |     920 |    |      |
|   1 |  HASH GROUP BY                   |          |      1 |      1 |    56 |     7  (15)| 00:00:01 |      3 |00:00:00.01 |     920 |   836K|   836K|  786K (0)|
|   2 |   NESTED LOOPS                   |          |      1 |      1 |    56 |     6   (0)| 00:00:01 |      3 |00:00:00.01 |     920 |    |      |
|   3 |    NESTED LOOPS                |          |      1 |      1 |    56 |     6   (0)| 00:00:01 |      3 |00:00:00.01 |     919 |    |      |
|   4 |     TABLE ACCESS BY INDEX ROWID BATCHED| EMP_P          |      1 |      1 |    36 |     3   (0)| 00:00:01 |    350 |00:00:00.01 |     234 |    |      |
|*  5 |      INDEX RANGE SCAN               | EMP_P_IX01   |      1 |      1 |    |     1   (0)| 00:00:01 |    350 |00:00:00.01 |       2 |    |      |
|*  6 |     INDEX RANGE SCAN               | ORDER_P_IX01 |    350 |      1 |    |     2   (0)| 00:00:01 |      3 |00:00:00.01 |     685 |    |      |
|   7 |    TABLE ACCESS BY INDEX ROWID           | ORDER_P      |      3 |      1 |    20 |     3   (0)| 00:00:01 |      3 |00:00:00.01 |       1 |    |      |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   5 - access("B"."EMPCD"='z0005')
   6 - access("EMPID"="B"."EMPID" AND "ORDERDT">='20140901' AND "ORDERDT"<='20140903')

 

 

S님 답안

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
SQL>
select /*+ gather_plan_statistics no_merge(a) push_pred(a) index(a emp_idx01) index(b order_idx01) */
a.empid, cnt 총주문횟수, price 총주문금액, qty 총주문량, dt 최종주문일자,
b.empnm, b.addr,b.phone from
(
select empid, count(*) cnt , sum(orderpric) price, sum(orderqty) qty,
max(orderdt) dt from order_p
where orderdt between '20140901' and '20140903'
group by empid
) a, emp_p b
where a.empid=b.empid
and b.empcd='z0005';
 
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULLNULL'ADVANCED ALLSTATS LAST'));
--------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                | Name           | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time     | A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |           |      1 |     |     |     7 (100)|      |    3 |00:00:00.01 |     923 |
|   1 |  NESTED LOOPS                |           |      1 |      1 |    81 |     7   (0)| 00:00:01 |    3 |00:00:00.01 |     923 |
|   2 |   TABLE ACCESS BY INDEX ROWID BATCHED    | EMP_P        |      1 |      1 |    36 |     3   (0)| 00:00:01 |    350 |00:00:00.01 |     235 |
|*  3 |    INDEX RANGE SCAN            | EMP_P_IX01   |      1 |      1 |     |     1   (0)| 00:00:01 |    350 |00:00:00.01 |       3 |
|   4 |   VIEW PUSHED PREDICATE         |           |    350 |      1 |    45 |     4   (0)| 00:00:01 |    3 |00:00:00.01 |     688 |
|*  5 |    FILTER                |           |    350 |     |     |          |      |    3 |00:00:00.01 |     688 |
|   6 |     SORT AGGREGATE            |           |    350 |      1 |    20 |          |      |    350 |00:00:00.01 |     688 |
|   7 |      TABLE ACCESS BY INDEX ROWID BATCHED| ORDER_P      |    350 |      1 |    20 |     4   (0)| 00:00:01 |    3 |00:00:00.01 |     688 |
|*  8 |       INDEX RANGE SCAN            | ORDER_P_IX01 |    350 |      1 |     |     3   (0)| 00:00:01 |    3 |00:00:00.01 |     686 |
--------------------------------------------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   3 - access("B"."EMPCD"='z0005')
   5 - filter(COUNT(*)>0)
   8 - access("EMPID"="B"."EMPID" AND "ORDERDT">='20140901' AND "ORDERDT"<='20140903')

 

 

모범답안1

merge 힌트는 따로 쓰지 않음
leading 힌트로 테이블 읽는 순서만 조정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
SQL>
select /*+ gather_plan_statistics leading(b) use_nl(a) index(b emp_p_ix01) index(a order_p_ix01) */ 
a.empid, cnt 총주문횟수, price 총주문금액, qty 총주문량, dt 최종주문일자, b.empnm, b.addr, b.phone
from
(
 select empid, count(*) cnt, sum(orderpric) price, sum(orderqty) qty, max(orderdt) dt
 from order_p
 where orderdt between '20140901' and '20140903'
 group by empid
) a, emp_p b
where a.empid = b.empid
and b.empcd = 'z0005';
 
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULLNULL'ADVANCED ALLSTATS LAST'));
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name          | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time    | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |          |      1 |    |    |     7 (100)|        |      3 |00:00:00.01 |     920 |    |      |
|   1 |  HASH GROUP BY                   |          |      1 |      1 |    56 |     7  (15)| 00:00:01 |      3 |00:00:00.01 |     920 |   836K|   836K|  779K (0)|
|   2 |   NESTED LOOPS                   |          |      1 |      1 |    56 |     6   (0)| 00:00:01 |      3 |00:00:00.01 |     920 |    |      |
|   3 |    NESTED LOOPS                |          |      1 |      1 |    56 |     6   (0)| 00:00:01 |      3 |00:00:00.01 |     919 |    |      |
|   4 |     TABLE ACCESS BY INDEX ROWID BATCHED| EMP_P          |      1 |      1 |    36 |     3   (0)| 00:00:01 |    350 |00:00:00.01 |     234 |    |      |
|*  5 |      INDEX RANGE SCAN               | EMP_P_IX01   |      1 |      1 |    |     1   (0)| 00:00:01 |    350 |00:00:00.01 |       2 |    |      |
|*  6 |     INDEX RANGE SCAN               | ORDER_P_IX01 |    350 |      1 |    |     2   (0)| 00:00:01 |      3 |00:00:00.01 |     685 |    |      |
|   7 |    TABLE ACCESS BY INDEX ROWID           | ORDER_P      |      3 |      1 |    20 |     3   (0)| 00:00:01 |      3 |00:00:00.01 |       1 |    |      |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   5 - access("B"."EMPCD"='z0005')
   6 - access("EMPID"="B"."EMPID" AND "ORDERDT">='20140901' AND "ORDERDT"<='20140903')

 

 

모범답안2

push_pred 활용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
SQL>
select /*+ gather_plan_statistics leading(b a) use_nl(a) index(b emp_p_ix01) index(a order_p_ix01) no_merge(a) push_pred(a)*/ 
a.empid, cnt 총주문횟수, price 총주문금액, qty 총주문량, dt 최종주문일자, b.empnm, b.addr, b.phone
from
(
 select empid, count(*) cnt, sum(orderpric) price, sum(orderqty) qty, max(orderdt) dt
 from order_p
 where orderdt between '20140901' and '20140903'
 group by empid
) a, emp_p b
where a.empid = b.empid
and b.empcd = 'z0005';
 
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULLNULL'ADVANCED ALLSTATS LAST'));
--------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                | Name           | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time     | A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |           |      1 |     |     |     7 (100)|      |    3 |00:00:00.01 |     923 |
|   1 |  NESTED LOOPS                |           |      1 |      1 |    81 |     7   (0)| 00:00:01 |    3 |00:00:00.01 |     923 |
|   2 |   TABLE ACCESS BY INDEX ROWID BATCHED    | EMP_P        |      1 |      1 |    36 |     3   (0)| 00:00:01 |    350 |00:00:00.01 |     235 |
|*  3 |    INDEX RANGE SCAN            | EMP_P_IX01   |      1 |      1 |     |     1   (0)| 00:00:01 |    350 |00:00:00.01 |       3 |
|   4 |   VIEW PUSHED PREDICATE         |           |    350 |      1 |    45 |     4   (0)| 00:00:01 |    3 |00:00:00.01 |     688 |
|*  5 |    FILTER                |           |    350 |     |     |          |      |    3 |00:00:00.01 |     688 |
|   6 |     SORT AGGREGATE            |           |    350 |      1 |    20 |          |      |    350 |00:00:00.01 |     688 |
|   7 |      TABLE ACCESS BY INDEX ROWID BATCHED| ORDER_P      |    350 |      1 |    20 |     4   (0)| 00:00:01 |    3 |00:00:00.01 |     688 |
|*  8 |       INDEX RANGE SCAN            | ORDER_P_IX01 |    350 |      1 |     |     3   (0)| 00:00:01 |    3 |00:00:00.01 |     686 |
--------------------------------------------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   3 - access("B"."EMPCD"='z0005')
   5 - filter(COUNT(*)>0)
   8 - access("EMPID"="B"."EMPID" AND "ORDERDT">='20140901' AND "ORDERDT"<='20140903')

* 본문 샘플데이터의 분포, DB 버전이 문제와 동일하지 않기 때문에 문제와 답안의 성능(결과)가 devDo님 결과와 다를수있음

* 상세 설명은 devDo님 설명참조

 

 

참조 : 

https://blog.naver.com/oracledo/220412608959

https://blog.naver.com/oracledo/220425668814