oracle 11g億級復雜SQL優化一例(數量級性能提升)


自從16年之后,因為工作原因,項目中就沒有再使用oracle了,最近最近支持一個項目,又要開始負責這塊事情了。最近在跑性能測試,配置全部調好之后,不少sql還存在性能低下的問題,主要涉及執行計划的不合理,以及相關pga隱含參數的優化。可能因為幾年不接觸的原因,略微有些生疏需要review了。這里以最近優化過的某個比較典型的例子為例(這里只講思路、因為涉及到敏感信息,不給出最終結果,16C E5620@2.40GHz/45GB內存/fio 85/15 iops 8500/1500 配置,優化前100G臨時空間都爆掉,到20分鍾出結果,實際上允許完全調整的話,最多5分鍾就可以運行出來),這個例子比較經典,它是一個產品轉換的例子,從業務邏輯上來看,它需要對兩個100w(100管理人*1w支產品)記錄的結果集進行黑名單(是指A產品->B產品是否允許轉換,A->B不允許,不意味着B->A不允許)以外的笛卡爾積關聯,,重點回顧下一些重要的operation以及如何通過hint強制,子查詢獨立運行時的operation和作為主查詢的子查詢運行時的operation不相同可能會造成性能差異巨大。首先,不要指望寫一段sql,既可以在oracle下運行、也可以在mysql下運行。原始的sql語句以及執行計划如下:

INSERT INTO C3(
                   tenantid,c_code,l_serialno,c_txtfundcode,
                   c_chargetype,f_sharemin,f_sharemax,l_hold,c_txtothercode,
                   c_targetchargetype,c_custtype,c_flag,d_operatedate,d_cdate,c_cyno)
            SELECT a.tenantid,a.c_code,l_serialno,
                   CASE a.agencytypes WHEN 'AB' THEN a.c_prdcode ELSE COALESCE(b.c_outprdcode,a.c_prdcode) END c_txtfundcode,
                   c_chargetype,f_sharemin,f_sharemax,l_hold,
                   CASE a.agencytypes WHEN 'AB'THEN a.c_othercode ELSE COALESCE(c.c_outprdcode,a.c_othercode) END c_txtothercode,
                   c_targetchargetype,c_custtype,c_flag,d_operatedate,20100511 d_cdate,a.c_cyno
              FROM (SELECT 0 l_serialno,
                           CASE t.c_mutextype WHEN 'A' THEN '0' WHEN 'B' THEN '1' WHEN 'C' THEN '2' ELSE t.c_mutextype END c_chargetype,
                           CASE t.c_targetsharetype WHEN 'A' THEN '0' WHEN 'B' THEN '1' WHEN 'C' THEN '2' ELSE t.c_targetsharetype END c_targetchargetype,
                           ar.f_cminmutex f_sharemin,99999999999999.9 f_sharemax,0 l_hold,'2' c_custtype,
                           '1' c_flag,'20000101' d_operatedate,
                           t.*
                      FROM (SELECT fo.tenantid, fo.c_code, fo.c_prdcode,fi.c_prdcode c_othercode,
                                   fo.c_cyno,fo.c_mutextype,fi.c_mutextype c_targetsharetype,
                                   fo.d_contractdate d_contractdate, fo.c_mutextypes c_mutextypes,
                                   fo.agencytypes,
                                   fi.d_contractdate d_othercontractdate, fi.c_mutextypes c_othersharetypes
                              FROM (SELECT DISTINCT ss.tenantid, ss.c_code, ss.c_prdcode,
                                                    ss.c_cyno,ss.c_mutextype c_mutextype,
                                                    ta.c_mutextypes agencytypes,
                                                    getsysvalue(ss.tenantid, ss.c_code, ss.c_cyno,ss.c_managercode, ss.c_prdcode,'ContractDate', '20991231') d_contractdate,
                                                    getsysvalue(ss.tenantid, ss.c_code, ss.c_cyno,ss.c_managercode, ss.c_prdcode,'ShareTypes', '') c_mutextypes
                                      FROM (SELECT fi.tenantid, fi.c_code, fi.c_prdcode,c.c_cyno,
                                                   s.c_mutextype, fi.c_managercode
                                              FROM FUNDINFO fi,
                                                   (SELECT 'A' c_mutextype FROM DUAL
                                                     UNION ALL
                                                    SELECT 'B' c_mutextype FROM DUAL
                                                     UNION ALL
                                                    SELECT 'C' c_mutextype FROM DUAL) s,
                                                   QUALIFY c,
                                                   EXPBATCH d
                                             WHERE fi.c_code   = 'F6'
                                               AND fi.tenantid = '*'
                                               AND fi.c_fundstatus NOT IN ('6', '9')
                                               AND c.c_code    = 'F6'
                                               AND c.tenantid  = '*'
                                               AND c.c_cyno  = d.c_cyno
                                               AND c.c_code    = d.c_code
                                               AND c.tenantid  = d.tenantid
                                               AND INSTR(fi.c_mutextypes, s.c_mutextype) > 0
                                               AND (fi.c_fundtype<>'1'
                                                   OR
                                                   NOT EXISTS(SELECT 1 FROM TEXT_PARAMETER
                                                               WHERE c_paramitem  = 'ChangeLimit'
                                                                 AND c_paramvalue = '1'
                                                                 AND c_prdcode   = fi.c_prdcode
                                                                 AND c_code     = 'F6'
                                                                 AND tenantid   = '*'))
                                               AND fi.c_prdcode  = c.c_prdcode
                                               AND c.c_issaleflag = '1'
                                           ) ss,
                                           EXPBATCH ta
                                     WHERE ss.c_cyno = ta.c_cyno
                                       AND ss.c_code   = ta.c_code
                                       AND ss.tenantid = ta.tenantid
                                       AND ta.c_notexpparamfiles = '0'
                                   ) fo,
                                   (SELECT DISTINCT ss.tenantid, ss.c_code, ss.c_prdcode,
                                                    ss.c_cyno,ss.c_mutextype c_mutextype,
                                                    getsysvalue(ss.tenantid, ss.c_code, ss.c_cyno,ss.c_managercode, ss.c_prdcode,'ContractDate', 20991231) d_contractdate,
                                                    getsysvalue(ss.tenantid, ss.c_code, ss.c_cyno,ss.c_managercode, ss.c_prdcode,'ShareTypes', '') c_mutextypes
                                      FROM (SELECT fi.tenantid, fi.c_code, fi.c_prdcode,
                                                   c.c_cyno, s.c_mutextype, fi.c_managercode
                                              FROM FUNDINFO fi,
                                                   (SELECT 'A' c_mutextype FROM DUAL
                                                     UNION ALL
                                                    SELECT 'B' c_mutextype FROM DUAL
                                                     UNION ALL
                                                    SELECT 'C' c_mutextype FROM DUAL) s,
                                                   QUALIFY c,
                                                   EXPBATCH d
                                             WHERE fi.c_code   = 'F6'
                                               AND fi.tenantid = '*'
                                               AND c.c_code    = 'F6'
                                               AND c.tenantid  = '*'
                                               AND c.c_cyno  = d.c_cyno
                                               AND c.c_code    = d.c_code
                                               AND c.tenantid  = d.tenantid
                                               AND INSTR(fi.c_mutextypes, s.c_mutextype) > 0
                                               AND fi.c_fundstatus NOT IN ('6', '9')
                                               AND (fi.c_fundtype <> '1'
                                                   OR NOT EXISTS
                                                   (SELECT 1 FROM TEXT_PARAMETER
                                                     WHERE c_paramitem  = 'ChangeLimit'
                                                       AND c_paramvalue = '1'
                                                       AND c_prdcode   = fi.c_prdcode
                                                       AND c_code     = 'F6'
                                                       AND tenantid   = '*'))
                                               AND fi.c_prdcode  = c.c_prdcode
                                               AND c.c_issaleflag = '1'
                                           ) ss,
                                           EXPBATCH ta
                                     WHERE ss.c_cyno = ta.c_cyno
                                       AND ss.c_code   = ta.c_code
                                       AND ss.tenantid = ta.tenantid
                                       AND ta.c_notexpparamfiles = '0'
                                   ) fi
                             WHERE fo.c_prdcode <> fi.c_prdcode
                               AND fo.c_mutextype = fi.c_mutextype
                               AND fo.c_cyno  = fi.c_cyno
                           ) t,(SELECT c_prdcode, c_cyno, MIN(a.f_cminmutex) f_cminmutex
                                  FROM ARLIMIT a
                                 WHERE c_cyno <> '*'
                                   AND c_code = 'F6'
                                   AND tenantid = '*'
                                 GROUP BY c_prdcode, c_cyno
                                UNION ALL
                                SELECT c_prdcode, b.c_cyno, MIN(f_cminmutex) f_cminmutex
                                  FROM ARLIMIT a, EXPBATCH b
                                 WHERE a.c_cyno = '*'
                                   AND a.c_code = 'F6'
                                   AND a.tenantid = '*'
                                   AND a.c_code = b.c_code
                                   AND a.tenantid = b.tenantid
                                   AND not exists (SELECT 1
                                                      FROM ARLIMIT c
                                                     WHERE b.c_cyno = c.c_cyno
                                                       AND a.c_prdcode = c.c_prdcode
                                                       AND a.c_code = c.c_code
                                                       AND a.tenantid = c.tenantid)
                                 GROUP BY c_prdcode, b.c_cyno) ar
                     WHERE t.d_contractdate <= 20100511
                       AND t.d_othercontractdate <= 20100511
                       AND INSTR(t.c_mutextypes, t.c_mutextype) > 0
                       AND INSTR(t.c_othersharetypes, t.c_targetsharetype) > 0
                       AND t.c_prdcode = ar.c_prdcode
                       AND t.c_cyno = ar.c_cyno
                       AND NOT EXISTS
                           (SELECT 1
                              FROM CHANGELIMIT b
                             WHERE t.c_prdcode         = b.c_prdcode
                               AND (t.c_mutextype       = b.c_mutextype  OR b.c_mutextype  = '*')
                               AND (t.c_cyno        = b.c_cyno   OR b.c_cyno   = '*')
                               AND (t.c_othercode       = b.c_othercode  OR b.c_othercode  = '*')
                               AND (t.c_targetsharetype = b.c_othershare OR b.c_othershare = '*')
                           )
                   ) a
                   LEFT JOIN FUNDCODECHANGE b
                          ON (a.c_prdcode  = b.c_prdcode
                         AND  a.c_mutextype = b.c_mutextype
                         AND  a.c_code    = b.c_code
                         AND  a.tenantid  = b.tenantid)
                   LEFT JOIN FUNDCODECHANGE c
                          ON (a.c_othercode = c.c_prdcode
                         AND  a.c_targetsharetype = c.c_mutextype
                         AND  a.c_code    = c.c_code
                         AND  a.tenantid  = c.tenantid)

 

 

 

-- 此處隱藏了謂詞部分
 Plan Hash Value  : 4256998962 

--------------------------------------------------------------------------------------------------------------------------
| Id   | Operation                                   | Name                      | Rows    | Bytes     | Cost | Time     |
--------------------------------------------------------------------------------------------------------------------------
|    0 | INSERT STATEMENT                            |                           |       1 |       129 | 2103 | 00:00:26 |
|    1 |   LOAD TABLE CONVENTIONAL                   | C3                        |         |           |      |          |
|    2 |    NESTED LOOPS OUTER                       |                           |       1 |       129 | 2103 | 00:00:26 |
|    3 |     VIEW                                    |                           |       1 |        95 | 2102 | 00:00:26 |
|  * 4 |      FILTER                                 |                           |         |           |      |          |
|  * 5 |       HASH JOIN                             |                           |       1 |      8105 | 2101 | 00:00:26 |
|  * 6 |        HASH JOIN                            |                           |       1 |      8078 | 1827 | 00:00:22 |
|    7 |         NESTED LOOPS OUTER                  |                           |       1 |      4060 |  914 | 00:00:11 |
|    8 |          VIEW                               |                           |       1 |      4026 |  913 | 00:00:11 |
|    9 |           SORT UNIQUE                       |                           |       1 |        72 |  913 | 00:00:11 |
| * 10 |            FILTER                           |                           |         |           |      |          |
|   11 |             NESTED LOOPS                    |                           |       1 |        72 |  912 | 00:00:11 |
|   12 |              NESTED LOOPS                   |                           |       1 |        72 |  912 | 00:00:11 |
|   13 |               NESTED LOOPS                  |                           |       1 |        58 |  911 | 00:00:11 |
|   14 |                NESTED LOOPS                 |                           |       1 |        49 |  910 | 00:00:11 |
|   15 |                 NESTED LOOPS                |                           |    1500 |     46500 |  309 | 00:00:04 |
|   16 |                  VIEW                       |                           |       3 |         9 |    6 | 00:00:01 |
|   17 |                   UNION-ALL                 |                           |         |           |      |          |
|   18 |                    FAST DUAL                |                           |       1 |           |    2 | 00:00:01 |
|   19 |                    FAST DUAL                |                           |       1 |           |    2 | 00:00:01 |
|   20 |                    FAST DUAL                |                           |       1 |           |    2 | 00:00:01 |
| * 21 |                  TABLE ACCESS FULL          | FUNDINFO              |     500 |     14000 |  101 | 00:00:02 |
| * 22 |                 TABLE ACCESS BY INDEX ROWID | QUALIFY           |       1 |        18 |    1 | 00:00:01 |
| * 23 |                  INDEX RANGE SCAN           | UIDX_QUALIFY         |       1 |           |    1 | 00:00:01 |
| * 24 |                INDEX RANGE SCAN             | PK_BATCH         |       1 |         9 |    1 | 00:00:01 |
| * 25 |               INDEX RANGE SCAN              | PK_EXPBATCH         |       1 |           |    1 | 00:00:01 |
| * 26 |              TABLE ACCESS BY INDEX ROWID    | EXPBATCH        |       1 |        14 |    1 | 00:00:01 |
| * 27 |             INDEX RANGE SCAN                | IDX_TEXTPARAMETER_VALUE   |       1 |        30 |    1 | 00:00:01 |
| * 28 |          TABLE ACCESS BY INDEX ROWID        | FUNDCODECHANGE        |       1 |        34 |    1 | 00:00:01 |
| * 29 |           INDEX UNIQUE SCAN                 | PK_FUNDCODECHANGE         |       1 |           |    1 | 00:00:01 |
|   30 |         VIEW                                |                           |       1 |      4018 |  913 | 00:00:11 |
|   31 |          SORT UNIQUE                        |                           |       1 |        69 |  913 | 00:00:11 |
| * 32 |           FILTER                            |                           |         |           |      |          |
|   33 |            NESTED LOOPS                     |                           |       1 |        69 |  912 | 00:00:11 |
|   34 |             NESTED LOOPS                    |                           |       1 |        69 |  912 | 00:00:11 |
|   35 |              NESTED LOOPS                   |                           |       1 |        58 |  911 | 00:00:11 |
|   36 |               NESTED LOOPS                  |                           |       1 |        49 |  910 | 00:00:11 |
|   37 |                NESTED LOOPS                 |                           |    1500 |     46500 |  309 | 00:00:04 |
|   38 |                 VIEW                        |                           |       3 |         9 |    6 | 00:00:01 |
|   39 |                  UNION-ALL                  |                           |         |           |      |          |
|   40 |                   FAST DUAL                 |                           |       1 |           |    2 | 00:00:01 |
|   41 |                   FAST DUAL                 |                           |       1 |           |    2 | 00:00:01 |
|   42 |                   FAST DUAL                 |                           |       1 |           |    2 | 00:00:01 |
| * 43 |                 TABLE ACCESS FULL           | FUNDINFO              |     500 |     14000 |  101 | 00:00:02 |
| * 44 |                TABLE ACCESS BY INDEX ROWID  | QUALIFY           |       1 |        18 |    1 | 00:00:01 |
| * 45 |                 INDEX RANGE SCAN            | UIDX_QUALIFY         |       1 |           |    1 | 00:00:01 |
| * 46 |               INDEX RANGE SCAN              | PK_EXPBATCH         |       1 |         9 |    1 | 00:00:01 |
| * 47 |              INDEX RANGE SCAN               | PK_EXPBATCH         |       1 |           |    1 | 00:00:01 |
| * 48 |             TABLE ACCESS BY INDEX ROWID     | EXPBATCH        |       1 |        11 |    1 | 00:00:01 |
| * 49 |            INDEX RANGE SCAN                 | IDX_TEXTPARAMETER_VALUE   |       1 |        30 |    1 | 00:00:01 |
|   50 |        VIEW                                 |                           |    7073 |    190971 |  274 | 00:00:04 |
|   51 |         UNION-ALL                           |                           |         |           |      |          |
|   52 |          SORT GROUP BY                      |                           |       1 |        16 |   20 | 00:00:01 |
|   53 |           TABLE ACCESS BY INDEX ROWID       | ARLIMIT               |       1 |        16 |   20 | 00:00:01 |
| * 54 |            INDEX FULL SCAN                  | UIDX_ARLIMIT             |       1 |           |   20 | 00:00:01 |
|   55 |          SORT GROUP BY                      |                           |    7072 |    275808 |  254 | 00:00:04 |
| * 56 |           HASH JOIN RIGHT ANTI              |                           | 2970075 | 115832925 |  175 | 00:00:03 |
| * 57 |            INDEX FULL SCAN                  | UIDX_ARLIMIT             |   30000 |    420000 |   20 | 00:00:01 |
| * 58 |            HASH JOIN                        |                           | 2970075 |  74251875 |  146 | 00:00:02 |
| * 59 |             INDEX FULL SCAN                 | PK_EXPBATCH         |      99 |       891 |    1 | 00:00:01 |
| * 60 |             TABLE ACCESS FULL               | ARLIMIT               |   30000 |    480000 |  137 | 00:00:02 |
| * 61 |       TABLE ACCESS BY INDEX ROWID           | CHANGELIMIT           |       1 |        28 |    1 | 00:00:01 |
| * 62 |        INDEX RANGE SCAN                     | IDX_CHANGELIMIT_FUNDCODE |      90 |           |    1 | 00:00:01 |
| * 63 |     TABLE ACCESS BY INDEX ROWID             | FUNDCODECHANGE        |       1 |        34 |    1 | 00:00:01 |
| * 64 |      INDEX UNIQUE SCAN                      | PK_FUNDCODECHANGE         |       1 |           |    1 | 00:00:01 |
--------------------------------------------------------------------------------------------------------------------------

這里不會講基礎優化,比如什么時候用hash join,什么時候nl,lio怎么看,access method,join method,fiter,predicate等基礎優化知識。

在某些情況下,查詢有left join時,使用了parallel會導致查詢一直出不來,不用parallel反而立刻可以出來。

在很多場景中,parallel提升性能很有限、甚至降低了性能以及並行執行中的buffer sort。在並行的執行計划中,我們可以看到有一步是buffer sort,而且這一步占據了挺長的時間,buffer sort實際上沒有排序,只是把數據加載到內存,不掃描多次表。通常在並行執行中出現這個操作。parallel為什么會性能提升有限呢,這其實涉及到oracle內部的算法是盡可能大部分場景最優化,這就會導致對於我們知道有規律的關聯消除並沒有被按預期消除,比如說在我們的這個優化中,每個管理人只有1w支產品,不同管理人之間是無法轉換的,但是oracle不知道,即使我們采用hash分區,且在管理人字段,設置最多100個分區(讀者肯定會問,為什么要使用hash分區而不是list呢?因為這里的管理人數量是不固定的,而我們使用的是oracle 11.2,如果是12c,就不存在這個問題了,因為12c支持了自動分區,見oracle 12cR1&12cR2核心高實用性新特性),也並不是每個分區一個管理人,很多分區沒有數據,所以導致分區間很不均衡,采用並行執行的時候,因為很不均衡,導致執行計划傾斜嚴重,可能高達40%。同時因為統計信息不一定准確,可能會導致某些時候應該px send hash的成了px send broadcast,這雖然可以通過pq_distriubte hint強制,但是由於優化器會在hint基礎上進一步進行查詢轉換(尤其涉及到子查詢套子查詢的時候),也可能會導致非預期的情況。實際上,對於超過三五個表以上復雜的sql,parallel效果就不佳的,這種情況,其實應該是應用里面發起多線程並行請求,采用fork-join模式來達到並行執行的效果。這一點只有掌握具體數據庫比如oracle/mysql優化原理(oracle做得到的mysql不一定做得到,反過來一般不成立)和實現的架構師做得到。最后,筆者會講到,本例是應該在設計上進行優化而不是單獨的oracle和sql優化的。

  • 執行計划相同,select很快,insert select很慢。比如帖子https://bbs.csdn.net/topics/370166028提到問題。對於結果記錄成千上萬的查詢,需要知道select只是fetch了前面幾行(即使優化器模式是all_rows),fetch也是要消耗lio的,所以如果不想insert 驗證下大概時間,至少需要select count(1) from (select /*+ no_merge*/ from ...),這樣才能得到相對比較合理的值(這個值可能和實際insert相差50%-100%之間,主要視數據量以及磁盤的速度而定)。有時候可能count(1)也很快,insert就很慢,執行計划又是完全相同的,這該怎么辦呢,結果數據量也不大,也就兩三百萬而已???還沒細看,最近真遇到這個例子了,
  • oracle insert select和select執行計划不同。參考insert select和select執行計划不同。
  • 主查詢中某子查詢的執行計划和子查詢獨立執行的執行計划不同。很有可能在子查詢獨立執行的時候,表之間的關聯采用了hash join,作為主查詢子句的時候,就是nl了,也有可能hash group by 變成了sort group by。這一點可以考慮使用with子句+materialize或者no_merge以及其他hint來控制住。
  • 多with子句,只有第一個被物化為臨時表。以前沒注意,這次發現有多個with的時候,只有第一個被物化,后面的都沒有被物化,雖然都加上了/*+ materialize */提示。如果實在無法控制執行計划,就考慮創建個臨時表吧(可惜oracle 12c之前,gtt和常規表一樣會產生大量的undo,oracle 12c引入了臨時undo表空間,可以極大的規避redo/undo的生成)。測試可見http://blog.itpub.net/7199859/viewspace-1150868/。
  • not exist中有and導致優化器選擇了filter。filter從實現上跟nl差不多,對於主查詢成千上萬的查詢,很可能一個filter就查詢不出來或者嚴重影響性能。通常not exist中會出現類似下列的語句:

and not exists (select /*+ qb_name(inn)*/* from inner_table inn where (inn.status = outer_table.status or inn.status = '1') and xxx)

對於這種情況,anti join就失效了,雖然可以讓主查詢使用nl加上/*+ push_subq(@inn) */來pushdown查詢條件,以避免主查詢使用hash join產生巨量中間結果,但是nl對於大表性能極為低下。此時可以考慮將not exists拆分為如下:

and not exists (select * from inner_table inn where (inn.status = '1') and xxx)

and not exists (select * from inner_table inn where (inn.status = outer_table.status or inn.status = '1') and xxx)

此時可能就可以做到第一個not exists采用hash anti過濾掉大部分最終結果不需要的數據集。

  • exist中有or導致優化器選擇了filter。對於exists,通常情況如下:

and exists (outer_table.status = '1' or select 1 from another_table x where x.type = outer_table.type and ... )

對於這類查詢,可以考慮使用union實現,但是有些時候,union並不見得合適,比如說查詢上使用了分析函數就不合適了。此時就需要考慮其他方法(因為在我們的另一個sql中,結果集還不算大,所以也就沒有進一步優化)。

  • 在java/c++中運行很慢,拷貝到pl/sql dev中執行就很快。其實了解oracle/mysql優化器原理的都知道綁定變量的概念,所以這就不足為奇了,要在pl/sql dev中完全模擬代碼中的行為,要么使用sql*plus的綁定變量,要么放到存儲過程(pl/sql默認綁定變量,除非使用execute immediate)中執行,就模擬了在代碼中的行為。
  • hash group by vs sort group by。hash group by 與 sort group by的區別,可以參考http://www.itpub.net/thread-1813825-1-1.html,要強制指定使用hash group by,可以使用/*+ NO_USE_HASH_AGGREGATION */提示。
  • SQL中調用了自定義函數時性能低下之。在sql語句中調用自定義函數是一大禁忌,內置函數之所以幾乎感覺不大太大的性能,是因為內置函數比如upper/lower都是確定性函數,也就是對於相同輸入、總是產生相同輸出,實際上在一個sql語句中,我們調用自定義函數的時候,做的通常都是類似參數/翻譯相關的功能,由於涉及到多個級別的優先級問題,所以一個sql語句實現較為復雜,所以在這個sql執行期間,通常不會是相同的輸入、產生不同的輸出,此時將自定義函數設置為DETERMINISTIC,在某些情況下,可以極大的提升性能(視在這個SQL執行期間,有多少比例的重復輸入而定)。但是,如果幾乎沒有重復的輸入,此時硬是將exists/not exists改為DETERMINISTIC自定義函數,將是悲劇。。
  • pga優化。workarea_size_policy模式下主要是pga_aggregate_target、_smm_px_max_size、_smm_max_size、_pga_max_size這四個參數,確定pga是否足夠只要查詢v$sql_plan_statistics_all,查看ONEPASS_EXECUTIONS、MULTIPASSES_EXECUTIONS、LAST_TEMPSEG_SIZE、MAX_TEMPSEG_SIZE這4個字段,只要MULTIPASSES_EXECUTIONS、LAST_TEMPSEG_SIZE、MAX_TEMPSEG_SIZE都為空或者0就可以保證pga足夠。
  • $session.event監控並優化服務器配置。當運行時間比較長的時候,我們需要查詢下v$session看下該進程當前在等待什么事件,根據此進一步確定是終止執行還是查看os的當前情況。
  • v$session_longops。對於並行執行(非並行執行不會體現),可以通過該視圖預估語句還需要執行多久,一般來說還是比較可靠的。
  • sar -d -p 5 10000。可以監控各個磁盤的飽和度情況,如下:

%util 90%以上就說明當前磁盤太忙,要么布局不合理,要么太慢了。

  • 問題很有可能在應用架構設計上,這事情已經超出了oracle的范圍。分而治之不是數據庫自身擅長的,這屬於應用設計的一部分,雖然類似分區、parallel算是分而自治的理念,但是它畢竟不知道業務上下文的特殊性,所以,對於這個sql,應該在SQL優化的基礎上,5或者10或者20個管理人作為條件,開管理人總數/每次處理的管理人作為線程數,采用fork-join模式實現,無論應用層是java還是c++都可以較為簡單的實現,三五分鍾完全是可以實現的(181114,我們最近將mysql版本進行了應用架構層的優化,將執行時間從27分鍾降低到了8分鍾,跑的比oracle還快)。
  • 對於復雜的sql,建議加上/*+ gather_plan_statistics */提示以便在v$sql_plan_statistics_all中收集實際的邏輯讀、物理讀、基數等值,以便進一步優化執行計划。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM