SELECT p.prod_category, c.country_id
, SUM(quantity_sold) AS quantity_sold
, SUM(amount_sold) AS amount_sold
FROM sales s
, customers c
, products p
WHERE s.cust_id = c.cust_id
AND s.prod_id = p.prod_id
GROUP BY p.prod_category, c.country_id
ORDER BY p.prod_category, c.country_id
;
-------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 68 | 3808 | | 2274 (4)| 00:00:28 | | |
| 1 | SORT GROUP BY | | 68 | 3808 | | 2274 (4)| 00:00:28 | | |
|* 2 | HASH JOIN | | 968 | 54208 | | 2273 (3)| 00:00:28 | | |
| 3 | VIEW | index$_join$_003 | 72 | 1512 | | 3 (34)| 00:00:01 | | |
|* 4 | HASH JOIN | | | | | | | | |
| 5 | INDEX FAST FULL SCAN| PRODUCTS_PK | 72 | 1512 | | 1 (0)| 00:00:01 | | |
| 6 | INDEX FAST FULL SCAN| PRODUCTS_PROD_CAT_IX | 72 | 1512 | | 1 (0)| 00:00:01 | | |
| 7 | VIEW | VW_GBC_9 | 968 | 33880 | | 2270 (3)| 00:00:28 | | |
| 8 | HASH GROUP BY | | 968 | 26136 | | 2270 (3)| 00:00:28 | | |
|* 9 | HASH JOIN | | 918K| 23M| 1200K| 2228 (2)| 00:00:27 | | |
| 10 | TABLE ACCESS FULL | CUSTOMERS | 55500 | 541K| | 406 (1)| 00:00:05 | | |
| 11 | PARTITION RANGE ALL| | 918K| 14M| | 494 (3)| 00:00:06 | 1 | 28 |
| 12 | TABLE ACCESS FULL | SALES | 918K| 14M| | 494 (3)| 00:00:06 | 1 | 28 |
-------------------------------------------------------------------------------------------------------------------------
2 - access("ITEM_1"="P"."PROD_ID")
4 - access(ROWID=ROWID)
9 - access("S"."CUST_ID"="C"."CUST_ID")
CREATE MATERIALIZED VIEW sales_mv
AS
SELECT p.prod_category, c.country_id
, SUM(quantity_sold) AS quantity_sold
, SUM(amount_sold) AS amount_sold
FROM sales s
, customers c
, products p
WHERE s.cust_id = c.cust_id
AND s.prod_id = p.prod_id
GROUP BY p.prod_category, c.country_id
ORDER BY p.prod_category, c.country_id
;
MView 직접 조회
SELECT * FROM sales_mv;
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 81 | 5346 | 3 (0)| 00:00:01 |
| 1 | MAT_VIEW ACCESS FULL| SALES_MV | 81 | 5346 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------------
MView 간접 조회(query rewrite 이용)
ALTER MATERIALIZED VIEW sales_mv ENABLE QUERY REWRITE;
SELECT p.prod_category, c.country_id
, SUM(quantity_sold) AS quantity_sold
, SUM(amount_sold) AS amount_sold
FROM sales s
, customers c
, products p
WHERE s.cust_id = c.cust_id
AND s.prod_id = p.prod_id
GROUP BY p.prod_category, c.country_id
ORDER BY p.prod_category, c.country_id
;
------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 81 | 5346 | 4 (25)| 00:00:01 |
| 1 | SORT ORDER BY | | 81 | 5346 | 4 (25)| 00:00:01 |
| 2 | MAT_VIEW REWRITE ACCESS FULL| SALES_MV | 81 | 5346 | 3 (0)| 00:00:01 |
------------------------------------------------------------------------------------------
범용 쿼리 재작성 시도 실패
SELECT UPPER(p.prod_category) prod_category
, SUM(s.amount_sold) amount_sold
FROM sales s
JOIN products p
ON s.prod_id = p.prod_id
GROUP BY p.prod_category
ORDER BY p.prod_category
;
-----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 | 190 | 539 (11)| 00:00:07 | | |
| 1 | SORT GROUP BY | | 5 | 190 | 539 (11)| 00:00:07 | | |
|* 2 | HASH JOIN | | 72 | 2736 | 538 (11)| 00:00:07 | | |
| 3 | VIEW | VW_GBC_5 | 72 | 1224 | 535 (11)| 00:00:07 | | |
| 4 | HASH GROUP BY | | 72 | 648 | 535 (11)| 00:00:07 | | |
| 5 | PARTITION RANGE ALL | | 918K| 8075K| 494 (3)| 00:00:06 | 1 | 28 |
| 6 | TABLE ACCESS FULL | SALES | 918K| 8075K| 494 (3)| 00:00:06 | 1 | 28 |
| 7 | VIEW | index$_join$_002 | 72 | 1512 | 3 (34)| 00:00:01 | | |
|* 8 | HASH JOIN | | | | | | | |
| 9 | INDEX FAST FULL SCAN| PRODUCTS_PK | 72 | 1512 | 1 (0)| 00:00:01 | | |
| 10 | INDEX FAST FULL SCAN| PRODUCTS_PROD_CAT_IX | 72 | 1512 | 1 (0)| 00:00:01 | | |
-----------------------------------------------------------------------------------------------------------------
2 - access("ITEM_1"="P"."PROD_ID")
8 - access(ROWID=ROWID)
범용 쿼리 재작성 재시도 성공
ALTER TABLE sales MODIFY CONSTRAINT sales_customer_fk VALIDATE;
ALTER TABLE customers MODIFY CONSTRAINT customers_pk VALIDATE;
SELECT UPPER(p.prod_category) prod_category
, SUM(s.amount_sold) amount_sold
FROM sales s
JOIN products p
ON s.prod_id = p.prod_id
GROUP BY p.prod_category
ORDER BY p.prod_category
;
------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 81 | 3240 | 4 (25)| 00:00:01 |
| 1 | SORT GROUP BY | | 81 | 3240 | 4 (25)| 00:00:01 |
| 2 | MAT_VIEW REWRITE ACCESS FULL| SALES_MV | 81 | 3240 | 3 (0)| 00:00:01 |
------------------------------------------------------------------------------------------
MView 정보 확인
SELECT refresh_method
, refresh_mode
, staleness
, last_refresh_type
, last_refresh_date
FROM user_mviews
WHERE mview_name = 'SALES_MV'
;
REFRESH_METHOD REFRESH_MODE STALENESS LAST_REFRESH_TYPE LAST_REFRESH_DATE
-------------- ------------ --------- ----------------- -----------------
FORCE DEMAND FRESH COMPLETE 18/01/18
dbms_mview 패키지로 MView Refresh 하기
dbms_mview.refresh(list => 'sh.sales_mv,sh.cal_month_sales_mv');
dbms_mview.refresh_all_mviews(number_of_failures => :r);
dbms_mview.refresh_dependent(number_of_failures => :r, list => 'sh.sales_mv');
mathod => ( c / f / p / ? : complete / fast / PCT / force )
atomic_refresh => false : complete refresh 수행시 deltet가 아닌 truncate 하고 수행하므로 빠름.
out_of_place => true : 새 컨테이너 테이블에 direct-path-insert 후 바꿔치기 (v12.1)
MView Refresh 주기적으로 하기
ALTER MATERIALIZED VIEW sales_mv
REFRESH COMPLETE ON DEMAND
START WITH sysdate
NEXT sysdate + TO_DSINTERVAL('0 00:10:00')
;
SELECT what, interval
FROM user_jobs
;
WHAT INTERVAL
---------------------------------------- -------------------------------------
dbms_refresh.refresh('"SH"."SALES_MV"'); sysdate + TO_DSINTERVAL('0 00:10:00')
MView log
CREATE MATERIALIZED VIEW LOG ON sales WITH ROWID;
CREATE MATERIALIZED VIEW LOG ON customers WITH ROWID;
CREATE MATERIALIZED VIEW LOG ON products WITH ROWID;
SELECT master, log_table
FROM user_mview_logs
WHERE master IN ('SALES', 'CUSTOMERS', 'PRODUCTS')
AND log_owner = 'SH'
;
MASTER LOG_TABLE
--------- -----------------
CUSTOMERS MLOG$_CUSTOMERS
PRODUCTS MLOG$_PRODUCTS
SALES MLOG$_SALES
MView log 재생성(fast refresh 를 지원하기 위함)
DROP MATERIALIZED VIEW LOG ON sales ;
DROP MATERIALIZED VIEW LOG ON customers;
DROP MATERIALIZED VIEW LOG ON products ;
CREATE MATERIALIZED VIEW LOG ON sales WITH ROWID, SEQUENCE
(cust_id, prod_id, quantity_sold, amount_sold) INCLUDING NEW VALUES;
CREATE MATERIALIZED VIEW LOG ON customers WITH ROWID, SEQUENCE
(cust_id, country_id) INCLUDING NEW VALUES;
CREATE MATERIALIZED VIEW LOG ON products WITH ROWID, SEQUENCE
(prod_id, prod_category) INCLUDING NEW VALUES;
MView 재생성(COUNT(*) 추가)
DROP MATERIALIZED VIEW sales_mv;
CREATE MATERIALIZED VIEW sales_mv
REFRESH FORCE ON DEMAND
AS
SELECT p.prod_category
, c.country_id
, SUM(s.quantity_sold) AS quantity_sold
, SUM(s.amount_sold) AS amount_sold
, COUNT(*) AS count_star
, COUNT(s.quantity_sold) AS count_quantity_sold
, COUNT(s.amount_sold) AS count_amount_sold
FROM sales s
, customers c
, products p
WHERE s.cust_id = c.cust_id
AND s.prod_id = p.prod_id
GROUP BY p.prod_category, c.country_id
;
fast refresh 수행시간 확인
INSERT INTO products
SELECT 619 prod_id
, prod_name
, prod_desc
, prod_subcategory
, prod_subcategory_id
, prod_subcategory_desc
, prod_category
, prod_category_id
, prod_category_desc
, prod_weight_class
, prod_unit_of_measure
, prod_pack_size
, supplier_id
, prod_status
, prod_list_price
, prod_min_price
, prod_total
, prod_total_id
, prod_src_id
, prod_eff_from
, prod_eff_to
, prod_valid
FROM products
WHERE prod_id = 136
;
INSERT INTO sales
SELECT 619 prod_id
, cust_id
, time_id
, channel_id
, promo_id
, quantity_sold
, amount_sold
FROM sales
WHERE prod_id = 136
;
COMMIT;
SQL> EXEC dbms_mview.refresh(list => 'sh.sales_mv', method => 'f');
PL/SQL 처리가 정상적으로 완료되었습니다.
경 과: 00:00:00.06 -- 빠르게 refresh 되었음을 확인 할 수 있다.
- 강좌 URL : http://www.gurubee.net/lecture/4403
- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.