今天收到了一位網友的SQL最佳化請求,
這個語句已經跑了快10天了,還沒出來,這位網友已經開始懷疑資料是否存在問題,儲存、網路哪方面肯定存在異常。
-
INSERT
/*+append*/
INTO
B nologging
-
SELECT
DISTINCT
'201707 AS bill_mon,t.product_id,user_nbr,node_id ,0 if_zeng,t1.product_name FROM A t
-
,bic.WASU_CP_Product_Type t1
-
WHERE to_char(etl_dt,'yyyymm
')='
201707
' and to_char(effective_dt,'
yyyymm
')<='
201706
'
-
and t.product_id=t1.product_id(+)
-
and NOT EXISTS(SELECT 1 FROM A t2
-
WHERE t2.node_id=t.node_id and t.user_nbr=t2.user_nbr
-
and t.product_id=t2.product_id
-
AND to_char(etl_dt,'yyyymm
')='
201706
' and to_char(effective_dt,'
yyyymm
')<='
201705
2、最佳化SQL第一步,獲取執行計劃
請使用以下語句獲取執行計劃
-
explain plan for
-
INSERT
/*+append*/
INTO
B nologging
-
SELECT
DISTINCT
'201707 AS bill_mon,t.product_id,user_nbr,node_id ,0 if_zeng,t1.product_name FROM A t
-
,bic.WASU_CP_Product_Type t1
-
WHERE to_char(etl_dt,'yyyymm
')='
201707
' and to_char(effective_dt,'
yyyymm
')<='
201706
'
-
and t.product_id=t1.product_id(+)
-
and NOT EXISTS(SELECT 1 FROM A t2
-
WHERE t2.node_id=t.node_id and t.user_nbr=t2.user_nbr
-
and t.product_id=t2.product_id
-
AND to_char(etl_dt,'yyyymm
')='
201706
' and to_char(effective_dt,'
yyyymm
')<='
201705;
-
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
以下是該網友發過來的執行計劃。
3、最佳化SQL第二步,
分析執行計劃
使用之前課程講解的游標化分析執行計劃步驟,
4、最佳化SQL第三步,分析操作關係
練習:
請問步驟3和步驟4、
步驟5和步驟6、
步驟2和步驟5,分別是之間講過的,單獨型、非關聯型、關聯型哪種?
5、最佳化SQL第四步,如何最佳化?
初步懷疑表BIC_ORDER_ALL_LOG統計資訊過舊,
1、查下統計資訊準不
select count(1) from bic_order_all_log_z;
select count(1) from bic_order_all_log_z where
to_char(etl_dt,'yyyymm
')='
201707
' and to_char(effective_dt,'
yyyymm
')<='
201706
';
透過以上查詢結果,可以判斷該表統計資訊過舊,造成CBO生成執行計劃異常。
最佳化方法一、從新收集統計資訊
本來計劃讓這位網友從新收集統計資訊,首先檢視所查詢表的統計資訊,
select owner,table_name,num_rows,last_analyzed from dba_tables where table_name='表名' and owner='使用者';
select owner,table_name,num_distinct from dba_tab_columns where table_name='表名' and owner='使用者';
select count(1) from 表名;
統計資訊一直未反饋,
這位網友是位資料庫開發,無法進行資料庫統計資訊收集。
練習:
現在問題來了,如果是您,如何從新收集該語句所查詢表的統計資訊?
最佳化方法二、hint法
最佳化後語句
SELECT '201707' AS bill_mon,t.product_id ,t1.product_name, t.user_nbr ,0 as if_tui,t.node_id
FROM bic.BIC_ORDER_all_LOG_Z t ,bic.WASU_CP_Product_Type t1
WHERE t.product_id=t1.product_id(+)
AND to_char(etl_dt,'yyyymm')='201707'
and to_char(effective_dt,'yyyymm')<='201706'
AND NOT EXISTS(SELECT /*+ use_hash(t, t2)*/1
FROM bic.BIC_ORDER_all_LOG_Z t2
WHERE to_char(etl_dt,'yyyymm')='201708' and to_char(effective_dt,'yyyymm')<='201707'
AND t.user_nbr=t2.user_nbr AND t.product_id=t2.product_id AND t.node_id=t2.node_id);
6、
最佳化SQL第五步,判定最佳化後SQL執行計劃
7、
最佳化SQL第六步,最佳化後執行時間
問
:
現在,多長時間出結果?
回覆:幾分鐘,
8、表的連線方法
SQL語句最佳化前10天查詢不出來,最佳化後幾分鐘出結果,透過以上最佳化案例,引出我們下面要討論的內容,表連線的方式有哪幾種:
-
Nested Loops Join
-
Hash Join
-
Sort Merge Join
-
Cartesian Join
以上4種表的連線方法,原理、
適用場景和優缺點各是什麼,請見下回分解???