微課sql最佳化(12)、表的連線方法(1)-幫助網友最佳化報表SQL

orastar發表於2020-03-04

1、問題來了

今天收到了一位網友的SQL最佳化請求, 這個語句已經跑了快10天了,還沒出來,這位網友已經開始懷疑資料是否存在問題,儲存、網路哪方面肯定存在異常。
  1. INSERT /*+append*/   INTO   B nologging
  2.         SELECT   DISTINCT   '201707 AS bill_mon,t.product_id,user_nbr,node_id ,0 if_zeng,t1.product_name FROM A t
  3.     ,bic.WASU_CP_Product_Type t1
  4.     WHERE to_char(etl_dt,'yyyymm ')=' 201707 ' and to_char(effective_dt,' yyyymm ')<=' 201706 '
  5.       and t.product_id=t1.product_id(+)
  6.       and NOT EXISTS(SELECT 1 FROM A t2 
  7.     WHERE t2.node_id=t.node_id and t.user_nbr=t2.user_nbr
  8.       and t.product_id=t2.product_id
  9.       AND to_char(etl_dt,'yyyymm ')=' 201706 ' and to_char(effective_dt,' yyyymm ')<=' 201705

2、最佳化SQL第一步,獲取執行計劃

請使用以下語句獲取執行計劃
  1. explain plan for
  2. INSERT /*+append*/   INTO  B nologging
  3.         SELECT   DISTINCT   '201707 AS bill_mon,t.product_id,user_nbr,node_id ,0 if_zeng,t1.product_name FROM A t
  4.     ,bic.WASU_CP_Product_Type t1
  5.     WHERE to_char(etl_dt,'yyyymm ')=' 201707 ' and to_char(effective_dt,' yyyymm ')<=' 201706 '
  6.       and t.product_id=t1.product_id(+)
  7.       and NOT EXISTS(SELECT 1 FROM A t2 
  8.     WHERE t2.node_id=t.node_id and t.user_nbr=t2.user_nbr
  9.       and t.product_id=t2.product_id
  10.       AND to_char(etl_dt,'yyyymm ')=' 201706 ' and to_char(effective_dt,' yyyymm ')<=' 201705;
  11. 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種表的連線方法,原理、 適用場景和優缺點各是什麼,請見下回分解???

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31442014/viewspace-2678268/,如需轉載,請註明出處,否則將追究法律責任。

相關文章