使用USE_HASH Hint調優一個SQL語句

abstractcyj發表於2016-09-12
開發的同事寫了個很長的SQL, 執行效率低下,於是找到我:
SQL如下:

點選(此處)摺疊或開啟

  1. SELECT w.wareid,
  2.        w.warename,
  3.        w.warespec,
  4.        w.wareunit,
  5.        w.factoryid,
  6.        w.bandcode,
  7.        w.lastpurprice,
  8.        ws.saleprice,
  9.        CASE
  10.          WHEN ws.saleprice = 0 THEN
  11.           0
  12.          ELSE
  13.           round((ws.saleprice - w.lastpurprice) / ws.saleprice, 4)
  14.        END mll,
  15.        fl.fl,
  16.        zkc.xl1,
  17.        s2.xl2,
  18.        zkc.xl5,
  19.        zkc.xl3,
  20.        zkc.xl4,
  21.        zbkc.zbkc,
  22.        CASE
  23.          WHEN nvl(xl4, 0) = 0 THEN
  24.           0
  25.          ELSE
  26.           round(zbkc.zbkc / xl4, 4)
  27.        END cxb,
  28.        zkc.zkc,
  29.        CASE
  30.          WHEN xl4 = 0 THEN
  31.           0
  32.          ELSE
  33.           round(zkc.zkc / xl4, 4)
  34.        END zcxb,
  35.        round(CASE
  36.                WHEN zkc.zkc = 0 THEN
  37.                 0
  38.                ELSE
  39.                 (zkc.zkc - zbkc.zbkc) / zkc.zkc
  40.              END,
  41.              4) fdkcbfb,
  42.        nvl(xl4, 0) * xs.xs - zbkc.zbkc bhl,
  43.        w.midqty,
  44.        v.cashtype,
  45.        nvl(h.sumpendingqty, 0) sumpendingqty,
  46.        s6.zdxl,
  47.        s6.zdxsje,
  48.        w.purstatus,
  49.        w.salestatus,
  50.        zkc.xsje,
  51.        zkc.zkcje,
  52.        zbkc.zbkcje,
  53.        w.purtax,
  54.        wc.classcode jx,
  55.        wb.fileno,
  56.        w.inittime,
  57.        we.we_num03,
  58.        we.we_lchar03,
  59.        w.store_req,
  60.        we.we_lchar02,
  61.        w.warningdays,
  62.        CASE
  63.          WHEN wc2.classcode = '3302' THEN
  64.           '是'
  65.          ELSE
  66.           '否'
  67.        END otc,
  68.        wc3.classcode,
  69.        w.waremark,
  70.        fl.vendorno1 gysbh,
  71.        fl.vendorno1,
  72.        w.lastvencusno,
  73.        fl.vendorno2,
  74.        1000 fdbh
  75.   FROM t_ware w
  76.   JOIN d_abcfl fl
  77.     ON w.wareid = fl.wareid
  78.   JOIN t_ware_class_base wc
  79.     ON w.wareid = wc.wareid
  80.    AND wc.classgroupno = '87'
  81.   JOIN d_bhxs xs
  82.     ON wc.classcode = xs.classcode
  83.    AND xs.abc = fl.fl
  84.   LEFT JOIN (SELECT h.compid,
  85.                     h.wareid,
  86.                     SUM(h.sumqty) zkc,
  87.                     SUM(h.sumqty * h.storepurprice) zkcje,
  88.                     SUM(h.lastyqty) xl1,
  89.                     SUM(h.lastm3qty) xl5,
  90.                     SUM(h.lastm2qty) xl3,
  91.                     SUM(h.lastmqty) xl4,
  92.                     SUM(h.lastmqty * h.storepurprice) xsje
  93.                FROM t_store_h h
  94.               GROUP BY h.compid, h.wareid) zkc
  95.     ON w.wareid = zkc.wareid
  96.    AND w.compid = zkc.compid
  97.   LEFT JOIN (SELECT h.compid,
  98.                     h.wareid,
  99.                     SUM(h.sumqty) zbkc,
  100.                     SUM(h.sumqty * h.storepurprice) zbkcje
  101.                FROM t_store_h h
  102.               WHERE h.busno = 1000
  103.               GROUP BY h.compid, h.wareid) zbkc
  104.     ON w.compid = zbkc.compid
  105.    AND w.wareid = zbkc.wareid
  106.   LEFT JOIN (SELECT rs.compid, rs.wareid, SUM(rs.wareqty) xl2
  107.                FROM t_rpt_sale rs
  108.               WHERE rs.accdate >= trunc(add_months(SYSDATE, -12) + 31)
  109.                 AND rs.accdate <= trunc(add_months(SYSDATE, -12) + 60)
  110.               GROUP BY rs.compid, rs.wareid) s2
  111.     ON w.compid = s2.compid
  112.    AND w.wareid = s2.wareid
  113.   LEFT JOIN (SELECT rs.compid,
  114.                     rs.wareid,
  115.                     SUM(rs.wareqty) zdxl,
  116.                     SUM(rs.netsum) zdxsje
  117.                FROM t_rpt_sale rs
  118.               WHERE rs.accdate >= to_date('2016/8/8', 'yyyy-mm-dd')
  119.                 AND rs.accdate <= to_date('2016/9/7', 'yyyy-mm-dd')
  120.               GROUP BY rs.compid, rs.wareid) s6
  121.     ON w.compid = s6.compid
  122.    AND w.wareid = s6.wareid
  123.   LEFT JOIN t_vencus v
  124.     ON w.lastvencusno = v.vencusno
  125.    AND w.compid = v.compid
  126.   LEFT JOIN t_store_h h
  127.     ON w.compid = h.compid
  128.    AND w.wareid = h.wareid
  129.    AND h.busno = 1000, t_ware_saleprice ws, t_ware_base wb,
  130.  t_ware_ext we, t_ware_class_base wc2, t_ware_class_base wc3
  131.  WHERE ws.salegroupid = 1
  132.    AND w.compid = ws.compid
  133.    AND w.wareid = ws.wareid
  134.    AND w.wareid = wb.wareid
  135.    AND w.wareid = we.wareid
  136.    AND w.compid = we.compid
  137.    AND w.wareid = wc2.wareid
  138.    AND wc2.classgroupno = '33'
  139.    AND w.wareid = wc3.wareid
  140.    AND wc3.classgroupno = '01'
  141.    AND w.compid = 2
auto trace結果如下:
|   0 | SELECT STATEMENT                           |                     |   397
 |   172K|  3934   (1)| 00:00:48 |                                              
                                                                                
|*  1 |  HASH JOIN                                 |                     |   397
 |   172K|  3934   (1)| 00:00:48 |                                              
                                                                                
|*  2 |   HASH JOIN                                |                     |   332
 |   140K|  3780   (1)| 00:00:46 |                                              
                                                                                
|   3 |    NESTED LOOPS                            |                     |   298
 |   122K|  3626   (1)| 00:00:44 |                                              
                                                                                
|   4 |     NESTED LOOPS                           |                     |   298
 |   122K|  3626   (1)| 00:00:44 |                                              
                                                                                
|   5 |      NESTED LOOPS OUTER                    |                     |   255
 |   101K|  3116   (1)| 00:00:38 |                                              
                                                                                
|*  6 |       HASH JOIN                            |                     |   255
 | 99195 |  3116   (1)| 00:00:38 |                                              
                                                                                
|*  7 |        HASH JOIN                           |                     |   255
 | 93585 |  3064   (1)| 00:00:37 |                                              
                                                                                
|*  8 |         HASH JOIN RIGHT OUTER              |                     |   255
 | 89760 |  2994   (1)| 00:00:36 |                                              
                                                                                
|*  9 |          TABLE ACCESS FULL                 | T_VENCUS            |   558
 |  6138 |    18   (0)| 00:00:01 |                                              
                                                                                
|  10 |          NESTED LOOPS OUTER                |                     |   255
 | 86955 |  2976   (1)| 00:00:36 |                                              
                                                                                
|* 11 |           HASH JOIN OUTER                  |                     |   255
 | 83130 |  2540   (1)| 00:00:31 |                                              
                                                                                
|  12 |            NESTED LOOPS OUTER              |                     |   255
 | 53295 |  1018   (1)| 00:00:13 |                                              
                                                                                
|* 13 |             HASH JOIN                      |                     |   255
 | 45645 |   253   (1)| 00:00:04 |                                              
                                                                                
|  14 |              TABLE ACCESS FULL             | D_ABCFL             |  5225
 | 36575 |     8   (0)| 00:00:01 |                                              
                                                                                
|* 15 |              HASH JOIN RIGHT OUTER         |                     |  1445
 |   242K|   245   (1)| 00:00:03 |                                              
                                                                                
|  16 |               VIEW                         |                     |     1
 |    52 |     0   (0)| 00:00:01 |                                              
                                                                                
|  17 |                HASH GROUP BY               |                     |     1
 |    61 |     0   (0)| 00:00:01 |                                              
                                                                                
|* 18 |                 TABLE ACCESS BY INDEX ROWID| T_RPT_SALE          |     1
 |    61 |     0   (0)| 00:00:01 |                                              
                                                                                
|  19 |                  INDEX FULL SCAN           | I_U_SALE_TWO        |     1
 |       |     0   (0)| 00:00:01 |                                              
                                                                                
|* 20 |               HASH JOIN                    |                     |  1445
 |   169K|   244   (1)| 00:00:03 |                                              
                                                                                
|* 21 |                HASH JOIN                   |                     |  1445
 | 33235 |   158   (1)| 00:00:02 |                                              
                                                                                
|  22 |                 TABLE ACCESS FULL          | D_BHXS              |    30
 |   330 |     4   (0)| 00:00:01 |                                              
                                                                                
|* 23 |                 TABLE ACCESS FULL          | T_WARE_CLASS_BASE   |  5631
 | 67572 |   154   (1)| 00:00:02 |                                              
                                                                                
|* 24 |                TABLE ACCESS FULL           | T_WARE              |  9860
 |   934K|    86   (0)| 00:00:02 |                                              
                                                                                
|  25 |             VIEW PUSHED PREDICATE          |                     |     1
 |    30 |     3   (0)| 00:00:01 |                                              
                                                                                
|  26 |              SORT GROUP BY                 |                     |     1
 |    19 |     3   (0)| 00:00:01 |                                              
                                                                                
|* 27 |               FILTER                       |                     |      
 |       |            |          |                                              
                                                                                
|  28 |                TABLE ACCESS BY INDEX ROWID | T_STORE_H           |     1
 |    19 |     3   (0)| 00:00:01 |                                              
                                                                                
|* 29 |                 INDEX UNIQUE SCAN          | PK_T_STORE_H        |     1
 |       |     2   (0)| 00:00:01 |                                              
                                                                                
|  30 |            VIEW                            |                     |  4942
 |   564K|  1523   (2)| 00:00:19 |                                              
                                                                                
|  31 |             HASH GROUP BY                  |                     |  4942
 |   115K|  1523   (2)| 00:00:19 |                                              
                                                                                
|* 32 |              TABLE ACCESS FULL             | T_STORE_H           |   487
K|    11M|  1510   (1)| 00:00:19 |                                              
                                                                                
|  33 |           TABLE ACCESS BY INDEX ROWID      | T_STORE_H           |     1
 |    15 |     2   (0)| 00:00:01 |                                              
                                                                                
|* 34 |            INDEX UNIQUE SCAN               | PK_T_STORE_H        |     1
 |       |     1   (0)| 00:00:01 |                                              
                                                                                
|* 35 |         TABLE ACCESS FULL                  | T_WARE_EXT          |  9823
 |   143K|    69   (0)| 00:00:01 |                                              
                                                                                
|  36 |        TABLE ACCESS FULL                   | T_WARE_BASE         |  9860
 |   211K|    52   (0)| 00:00:01 |                                              
                                                                                
|  37 |       VIEW PUSHED PREDICATE                |                     |     1
 |    17 |     0   (0)| 00:00:01 |                                              
                                                                                
|  38 |        SORT GROUP BY                       |                     |     1
 |    48 |     0   (0)| 00:00:01 |                                              
                                                                                
|* 39 |         FILTER                             |                     |      
 |       |            |          |                                              
                                                                                
|* 40 |          TABLE ACCESS BY INDEX ROWID       | T_RPT_SALE          |     1
 |    48 |     0   (0)| 00:00:01 |                                              
                                                                                
|* 41 |           INDEX RANGE SCAN                 | I_U_SALE_TWO        |     1
 |       |     0   (0)| 00:00:01 |                                              
                                                                                
|* 42 |      INDEX UNIQUE SCAN                     | PK_T_WARE_SALEPRICE |     1
 |       |     1   (0)| 00:00:01 |                                              
                                                                                
|  43 |     TABLE ACCESS BY INDEX ROWID            | T_WARE_SALEPRICE    |     1
 |    15 |     2   (0)| 00:00:01 |                                              
                                                                                
|* 44 |    TABLE ACCESS FULL                       | T_WARE_CLASS_BASE   |  9447
 |   110K|   154   (1)| 00:00:02 |                                              
                                                                                
|* 45 |   TABLE ACCESS FULL                        | T_WARE_CLASS_BASE   | 10191
 |   119K|   154   (1)| 00:00:02 |                                              
                                                                                
--------------------------------------------------------------------------------
----------------------------------                                              
                                                                                
                                                                                
Predicate Information (identified by operation id):                             
---------------------------------------------------                             
                                                                                
   1 - access("W"."WAREID"="WC2"."WAREID")                                      
   2 - access("W"."WAREID"="WC3"."WAREID")                                      
   6 - access("W"."WAREID"="WB"."WAREID")                                       
   7 - access("W"."WAREID"="WE"."WAREID" AND "W"."COMPID"="WE"."COMPID")        
   8 - access("W"."COMPID"="V"."COMPID"(+) AND "W"."LASTVENCUSNO"="V"."VENCUSNO"
(+))                                                                            
                                                                                
   9 - filter("V"."COMPID"(+)=2)                                                
  11 - access("W"."COMPID"="ZKC"."COMPID"(+) AND "W"."WAREID"="ZKC"."WAREID"(+))
  13 - access("XS"."ABC"="FL"."FL" AND "W"."WAREID"="FL"."WAREID")              
  15 - access("W"."WAREID"="S6"."WAREID"(+) AND "W"."COMPID"="S6"."COMPID"(+))  
  18 - filter("RS"."COMPID"=2 AND "RS"."ACCDATE">=TO_DATE(' 2016-08-08 00:00:00'
, 'syyyy-mm-dd                                                                  
                                                                                
              hh24:mi:ss') AND "RS"."ACCDATE"<=TO_DATE(' 2016-09-07 00:00:00', '
syyyy-mm-dd hh24:mi:ss'))                                                       
                                                                                
  20 - access("W"."WAREID"="WC"."WAREID")                                       
  21 - access("WC"."CLASSCODE"="XS"."CLASSCODE")                                
  23 - filter("WC"."CLASSCODE" IS NOT NULL AND "WC"."CLASSGROUPNO"='87')        
  24 - filter("W"."COMPID"=2)                                                   
  27 - filter("W"."COMPID"=2)                                                   
  29 - access("H"."COMPID"=2 AND "H"."BUSNO"=1000 AND "H"."WAREID"="W"."WAREID")
  32 - filter("H"."COMPID"=2)                                                   
  34 - access("H"."COMPID"(+)=2 AND "H"."BUSNO"(+)=1000 AND "W"."WAREID"="H"."WA
REID"(+))                                                                       
                                                                                
  35 - filter("WE"."COMPID"=2)                                                  
  39 - filter(TRUNC(ADD_MONTHS(SYSDATE@!,-12)+60)>=TRUNC(ADD_MONTHS(SYSDATE@!,-1
2)+31) AND "W"."COMPID"=2)                                                      
                                                                                
  40 - filter("RS"."COMPID"=2 AND "RS"."ACCDATE">=TRUNC(ADD_MONTHS(SYSDATE@!,-12
)+31) AND                                                                       
                                                                                
              "RS"."ACCDATE"<=TRUNC(ADD_MONTHS(SYSDATE@!,-12)+60))              
  41 - access("RS"."WAREID"="W"."WAREID")                                       
  42 - access("WS"."COMPID"=2 AND "WS"."SALEGROUPID"=1 AND "W"."WAREID"="WS"."WA
REID")                                                                          
                                                                                
  44 - filter("WC3"."CLASSGROUPNO"='01')                                        
  45 - filter("WC2"."CLASSGROUPNO"='33')                                        




統計資訊
----------------------------------------------------------                      
          1  recursive calls                                                    
          0  db block gets                                                      
      91720  consistent gets                                                    
          0  physical reads                                                     
          0  redo size                                                          
     784821  bytes sent via SQL*Net to client                                   
       4348  bytes received via SQL*Net from client                             
        350  SQL*Net roundtrips to/from client                                  
      10450  sorts (memory)                                                     
          0  sorts (disk)                                                       
       5224  rows processed 

這個SQL幾個表都是全表掃描,由於是查詢的所有商品的資訊(零售行業),所以調整表掃描方式等途徑想提升效率提升會很有限。

從這個執行計劃來看,子檢視zkc實際有幾萬條記錄,T_WARE資料也有幾千條。CBO選擇了NESTED LOOP進行表連線。由於資料量較大,這裡採用HASH JOIN應當效率較高

強制CBO選擇HASH JOIN
 SELECT /*+ USE_HASH(zkc)  */ ****

 hint加入之後,效果很顯著,原來需要6分多才能執行完成,採用HASH JOIN之後,15秒不到就執行完成




前後資料記錄有差別是因為寫這個部落格的時候,環境已經變化。
但是可以看到,邏輯讀的數量已經不是一個數量級的。




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

相關文章