/*
Test DB : Oracle Enterprise 12.2.0.1 Single
*/
-- 01. test table 생성
CREATE TABLE "SCOTT"."MYTEST"
(
"ID" VARCHAR2(50) NOT NULL ENABLE,
"UPDATED" DATE NOT NULL ENABLE,
"MYNAME" VARCHAR2(100) NOT NULL ENABLE,
PRIMARY KEY ("ID", "UPDATED")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE
STATISTICS
TABLESPACE "USERS" ENABLE
) SEGMENT CREATION DEFERRED
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
NOCOMPRESS LOGGING
TABLESPACE "USERS"
-- 02. 통계정보 설정
BEGIN
dbms_stats.set_column_stats ('SCOTT', 'MYTEST', 'ID', distcnt => 8 );
dbms_stats.set_column_stats ('SCOTT', 'MYTEST','UPDATED', distcnt => 300000);
dbms_stats.set_table_stats ('SCOTT', 'MYTEST', NUMROWS => 2400000);
dbms_stats.set_index_stats ('SCOTT', 'SYS_C0011249', NUMROWS => 2400000);
END;
-- 03. 원본 쿼리
SELECT *
FROM mytest T1
WHERE T1.updated = (SELECT max(updated)
FROM mytest
WHERE id = T1.id);
Plan hash value: 4215771275
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 8 | 992 | 2 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 8 | 992 | 2 (0)| 00:00:01 |
| 2 | NESTED LOOPS | | 8 | 992 | 2 (0)| 00:00:01 |
| 3 | VIEW | VW_SQ_1 | 8 | 288 | 1 (0)| 00:00:01 |
| 4 | HASH GROUP BY | | 8 | 288 | 1 (0)| 00:00:01 |
| 5 | INDEX FULL SCAN | SYS_C0011249 | 2400K| 82M| 1 (0)| 00:00:01 |
|* 6 | INDEX UNIQUE SCAN | SYS_C0011249 | 1 | | 1 (0)| 00:00:01 |
| 7 | TABLE ACCESS BY INDEX ROWID| MYTEST | 1 | 88 | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
6 - access("ITEM_1"="T1"."ID" AND "T1"."UPDATED"="MAX(UPDATED)")
-- 04. 쿼리 변형
select *
from mytest aa,
(select /*+ index_ffs(bb) */
id, max(updated) as updated
from mytest bb
group by ID
) cc
where aa.id = cc.id
and aa.UPDATED = cc.updated
;
Plan hash value: 198263429
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 8 | 992 | 69 (96)| 00:00:01 |
| 1 | NESTED LOOPS | | 8 | 992 | 69 (96)| 00:00:01 |
| 2 | NESTED LOOPS | | 8 | 992 | 69 (96)| 00:00:01 |
| 3 | VIEW | | 8 | 288 | 68 (98)| 00:00:01 |
| 4 | HASH GROUP BY | | 8 | 288 | 68 (98)| 00:00:01 |
| 5 | INDEX FAST FULL SCAN | SYS_C0011249 | 2400K| 82M| 2 (0)| 00:00:01 |
|* 6 | INDEX UNIQUE SCAN | SYS_C0011249 | 1 | | 1 (0)| 00:00:01 |
| 7 | TABLE ACCESS BY INDEX ROWID| MYTEST | 1 | 88 | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
6 - access("AA"."ID"="CC"."ID" AND "AA"."UPDATED"="CC"."UPDATED")
select
*
from mytest aa,
(select /*+ parallel_index(bb, 2) index_ffs(bb) */
id, max(updated) as updated
from mytest bb
group by ID
) cc
where aa.id = cc.id
and aa.UPDATED = cc.updated
;
Plan hash value: 1395081935
----------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
----------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 8 | 992 | 38 (93)| 00:00:01 | | | |
| 1 | PX COORDINATOR | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10001 | 8 | 992 | 38 (93)| 00:00:01 | Q1,01 | P->S | QC (RAND) |
| 3 | NESTED LOOPS | | 8 | 992 | 38 (93)| 00:00:01 | Q1,01 | PCWP | |
| 4 | NESTED LOOPS | | 8 | 992 | 38 (93)| 00:00:01 | Q1,01 | PCWP | |
| 5 | VIEW | | 8 | 288 | 73 (98)| 00:00:01 | Q1,01 | PCWP | |
| 6 | HASH GROUP BY | | 8 | 288 | 73 (98)| 00:00:01 | Q1,01 | PCWP | |
| 7 | PX RECEIVE | | 8 | 288 | 73 (98)| 00:00:01 | Q1,01 | PCWP | |
| 8 | PX SEND HASH | :TQ10000 | 8 | 288 | 73 (98)| 00:00:01 | Q1,00 | P->P | HASH |
| 9 | HASH GROUP BY | | 8 | 288 | 73 (98)| 00:00:01 | Q1,00 | PCWP | |
| 10 | PX BLOCK ITERATOR | | 2400K| 82M| 2 (0)| 00:00:01 | Q1,00 | PCWC | |
| 11 | INDEX FAST FULL SCAN| SYS_C0011249 | 2400K| 82M| 2 (0)| 00:00:01 | Q1,00 | PCWP | |
|* 12 | INDEX UNIQUE SCAN | SYS_C0011249 | 1 | | 1 (0)| 00:00:01 | Q1,01 | PCWP | |
| 13 | TABLE ACCESS BY INDEX ROWID| MYTEST | 1 | 88 | 1 (0)| 00:00:01 | Q1,01 | PCWP | |
----------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
12 - access("AA"."ID"="CC"."ID" AND "AA"."UPDATED"="CC"."UPDATED")
--
-- Table 에 MYNAME 칼럼이 없다면
--
SELECT /*+ index_ffs(T1, SYS_C0011249) */
*
FROM mytest T1
WHERE T1.UPDATED = (
select
UPDATED
from
(SELECT
/*+ index_desc(mytest, SYS_C0011249) */
updated
FROM mytest
WHERE id = T1.id
ORDER BY updated DESC
)
where rownum <= 1
);
Plan hash value: 2051182498
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 36 | 3 (0)| 00:00:01 |
|* 1 | FILTER | | | | | |
| 2 | INDEX FAST FULL SCAN | SYS_C0011249 | 1 | 36 | 2 (0)| 00:00:01 |
|* 3 | COUNT STOPKEY | | | | | |
| 4 | VIEW | | 1 | 9 | 1 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN DESCENDING| SYS_C0011249 | 1 | 36 | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("T1"."UPDATED"= (SELECT "UPDATED" FROM (SELECT /*+ INDEX_DESC ("MYTEST"
"SYS_C0011249") */ "UPDATED" "UPDATED" FROM "MYTEST" "MYTEST" WHERE "ID"=:B1 ORDER BY
"UPDATED" DESC) "from$_subquery$_002" WHERE ROWNUM<=1))
3 - filter(ROWNUM<=1)
5 - access("ID"=:B1)
select t1.*
FROM
(
SELECT
aa.id,
aa.updated
FROM
(
SELECT
t1.id,
t1.updated,
rank() over (partition BY id ORDER BY updated DESC) AS rnum
FROM mytest t1
) aa
WHERE rnum <= 1
) bb, mytest t1
where t1.id = bb.id
and t1.updated = bb.updated
;
2017년 8월 16일 수요일
갑자기 고민을 해본 어느 SQL
피드 구독하기:
덧글 (Atom)