索引覆蓋分析

系統優化期間,須要找到優化後最能帶來效益的點進行優化,這樣才能從根本上提高系統運行效率。sql


如下內容以某個保單增量處理程序邏輯進行分析。當前增量保單事實提取過程分爲如下兩步:
a. 經過upd_time增量查詢出各個關聯表的增量cntr_id主鍵並插入tmp_f_cntr_v8_cntrrange臨時表;
b. 經過tmp_f_cntr_v8_cntrrange表與std_contract等表JOIN操做,獲取增量保單數據。


1. 增量範圍肯定
1.1 業務行爲共用增量控制表:
當前現狀描述:互不交叉的業務行爲(例如新契約個單、合同團單、新契約團單等)共用同一張tmp_f_cntr_v8_cntrrange增量控制表,以下:

問題:
不一樣業務行爲共用tmp_f_cntr_v8_cntrrange增量表,同時都採用tmp_f_cntr_v8_cntrrange表提取增量數據,無故成倍地增長了增量數據範圍。


解決方案:
應該爲各業務行爲建立單獨的增量表(例如tmp_f_cntr_v8_cntrrange_appl_psn、tmp_f_cntr_v8_cntrrange_appl_grp、tmp_f_cntr_v8_cntrrange_cntr_grp等),並經過這些增量表提取保單數據。


1.2 upd_time肯定增量保單範圍:
當前現狀描述:
代碼以下:app

 
  1. select cntr_idas CNTR_NO,'999'as POL_CODE,'2'as APP_STD_FLAG from std_contract where upd_time>=?and upd_time<?  
  2. union  
  3. select distinctcntr_id as CNTR_NO,'999'as POL_CODE,'2'as APP_STD_FLAG from cntr_basic_state whereupd_time>=?and upd_time<?  
  4. union  
  5. select distinctcntr_id as CNTR_NO,'999'as POL_CODE,'2'as APP_STD_FLAG from cntr_sub_state where upd_time>=?and upd_time<?  
  6. union  
  7. select distinctcntr_id as CNTR_NO,'999'as POL_CODE,'2'as APP_STD_FLAG from insured whereupd_time>=? and upd_time<?  
  8. union  
  9. select distinctcntr_id as CNTR_NO,'999'as POL_CODE,'2'as APP_STD_FLAG from psn_cntr_holder whereupd_time>=?and upd_time<?  
  10. union  
  11. select distinctcntr_id as CNTR_NO,'999'as POL_CODE,'2'as APP_STD_FLAG from if_of_alt whereupd_time>=? and upd_time<?  
  12. union  
  13. select distinctstd_contract.cntr_idas CNTR_NO,'999'as POL_CODE,'2'as APP_STD_FLAG from grant_tranlst,std_contractwhere std_contract.cntr_no=grant_tranlst.cntr_noand grant_tranlst.upd_time>=?and grant_tranlst.upd_time<?  
  14. union  
  15. select distinctcntr_id as CNTR_NO,'999'as POL_CODE,'2'as APP_STD_FLAG from insur_appl_cv_task,std_contractwhere insur_appl_cv_task.rel_key_no=std_contract.appl_noand insur_appl_cv_task.upd_time>=?and insur_appl_cv_task.upd_time<?  

問題:
目前在相關表上的upd_time字段(也只此字段)均加了索引,可是要得到cntr_id時,仍然須要經過lookup rid到原始表中取出cntr_id字段(索引葉子節點沒有cntr_id)。這裏存在三點問題:
1). lookup rid以獲得cntr_id的操做,是upd_time索引查找範圍語句資源消耗的大頭,lookup rid只適合於小數據量;
2). lookup rid查找原表(由於有不少其餘任務訪問原表)會增長系統阻塞的機率及下降I/O量;
3). 可能會由於返回數據量大,使得upd_time索引失效。
優化方法:
每張表修改upd_time索引,經過在索引中包含相關字段(例如cntr_id),消除lookup rid操做,將整個增量查找過程轉換爲索引查找,能夠完全解決以上三個問題
2. 保單增量事實獲取:
當前現狀描述:
獲取保單增量事實的代碼可參見後文《優化前.sql》。
問題:
全部的相關表都是全表(這些表都是大表。固然,語句中有where語句,但仍然是從全表中過濾數據)JOIN,並經過tmp_f_cntr_v8_cntrrange增量範圍表提取出增量數據。這裏面存在如下問題:
1). 全部表(例如std_contract、cntr_sub_state等)均經過where語句,以及與tmp_f_cntr_v8_cntrrange表關聯獲得增量數據。這依賴於where語句中的索引,以及和tmp_f_cntr_v8_cntrrange表的關聯索引狀況,不然極可能引發全表掃描(這種狀況很是可怕);
2). 在上文1.2肯定增量範圍時,upd_time索引以及lookup rid已經獲得了各個表的增量數據,獲取保單事實的時候對同一張表又作了一次重複的訪問,沒有必要;
3). 通過分析,對絕大部分表(都是大表)使用的字段都很是的少,進行全表操做很是的不划算。
解決方案:
整合「肯定保單增量範圍」、「提取保單事實」兩個步驟:
絕大部分表的「保單事實使用到的字段」上建立索引(若是包含upd_time,可同時解決增量範圍的問題),能夠將表掃描轉換爲索引掃描(字段少因此索引會很小),徹底能夠下降系統阻塞(由於只須要訪問索引,不須要和其它任務爭搶原表),下降I/O量;優化

優化前:spa

 
  1. SELECT e.PROV_BRANCH_CODE                                     AS PROV_BRANCH_CODE,  
  2.        a.appl_no                                              AS APPL_NO,  
  3.        a.cntr_no                                              AS CNTR_NO,  
  4.        CASE  
  5.          WHEN a.mr_type = 'M' THEN a.cntr_no  
  6.          ELSE (SELECT TOP 1 cntr_no  
  7.                FROM   std_contractwith(nolock)  
  8.                WHERE  a.master_cntr_id = std_contract.cntr_id  
  9.                       AND std_contract.incr_flag <> '2')  
  10.        END                                                    ASMASTER_CNTR_NO,  
  11.        a.sg_no                                                ASSG_NO,  
  12.        Ltrim(Rtrim(CONVERT(VARCHAR(6), a.mgr_branch_no)))     AS TOWN_BRANCH_CODE,  
  13.        dbo.Pub_salesno(a.n_sales_branch_no, a.n_sales_code, 8)AS KEY_SALER_ID,  
  14.        Isnull(a.n_sales_branch_no, '!')                       ASBRANCH_NO,  
  15.        Isnull(a.n_sales_code, '!')                            AS AGENT_NO,  
  16.        a.sales_channel                                        AS SALES_CHANNEL_CODE,  
  17.        '!'                                                    ASMANAGE_CHANNEL_CODE,  
  18.        '!'                                                    ASCENTER_CODE,  
  19.        a.pol_code                                             ASPOL_CODE,  
  20.        CASE  
  21.          WHEN a.moneyin_itrvl = 'W' THEN 1  
  22.          ELSE b.moneyin_dur  
  23.        END                                                    ASMONEY_DUR,  
  24.        a.moneyin_itrvl                                        AS ITRVL_CODE,  
  25.        d.ipsn_cust_no                                         AS KEY_IPSN_CUST_ID,  
  26.        (SELECT TOP1 hldr_cust_no  
  27.         FROM   psn_cntr_holderwith(nolock)  
  28.         WHERE  a.cntr_id = psn_cntr_holder.cntr_id  
  29.                AND psn_cntr_holder.incr_flag <> '2'  
  30.         ORDER  BY psn_cntr_holder.upd_timeDESC)               ASKEY_HLDR_CUST_ID,  
  31.        CASE  
  32.          WHEN b.insur_dur_unit = 'W' THEN 999  
  33.          ELSE b.insur_dur  
  34.        END                                                    ASINSUR_DUR,  
  35.        a.in_force_date                                        AS IN_FORCE_DATE,  
  36.        a.sign_date                                            AS SIGN_DATE,  
  37.        a.cntr_term_date                                       AS TERM_DATE,  
  38.        CASE  
  39.          WHEN a.cg_no IS NULL THEN (SELECT TOP 1 Cast(ext_key12 AS DATETIME)  
  40.                                     FROM   insur_appl_cv_task h WITH(nolock)  
  41.                                     WHERE  a.appl_no = h.rel_key_no  
  42.                                            AND a.cntr_no = h.ext_key9  
  43.                                            AND Isdate(h.ext_key12) = 1  
  44.                                            AND h.incr_flag <> '2'  
  45.                                     ORDER  BY task_seq DESC)  
  46.          ELSE (SELECT TOP 1 Cast(ext_key12 AS DATETIME)  
  47.                FROM   insur_appl_cv_taskh WITH(nolock)  
  48.                WHERE  a.appl_no = h.rel_key_no  
  49.                       AND a.cg_no = h.ext_key9  
  50.                       AND Isdate(h.ext_key12) = 1  
  51.                       AND h.incr_flag <> '2'  
  52.                ORDER  BY task_seq DESC)  
  53.        END                                                    ASRESP_DATE,  
  54.        a.mr_type                                              AS MR_TYPE_CODE,  
  55.        a.cntr_stat                                            AS CNTR_STAT,  
  56.        a.cntr_type                                            AS CNTR_TYPE_CODE,  
  57.        8                                                      ASDATA_SRC_ID,  
  58.        z.std_premium                                          AS FACT_STD_PREM,  
  59.        z.face_amnt                                            AS FACT_FACE_AMNT,  
  60.        d.ipsn_num                                             AS FACT_IPSN_NUM,  
  61.        a.cntr_term_cause                                      AS CNTR_STOP_CODE,  
  62.        z.stop_moneyin_date                                    AS STOP_MONEYIN_DATE,  
  63.        a.cntr_expiry_date                                     AS EXPIRY_DATE,  
  64.        f.out_force_date                                       AS OUT_FORCE_DATE,  
  65.        f.re_in_force_date                                     AS RE_IN_FORCE_DATE,  
  66.        Substring(a.appl_no, 1, 4)                             AS CARD_CODE,  
  67.        CASE  
  68.          WHEN a.Sales_channelin('OA', 'SP') THEN dbo.Pub_salesno(a.n_sales_branch_no, a.n_sales_code, 8)  
  69.          ELSE '-1'  
  70.        END                                                    ASKEY_SITE_ID,  
  71.        Dateadd(day, -1, auto_in_force_date)                   ASENROLL_DATE,  
  72.        (SELECT TOP1 contact_seq  
  73.         FROM   psn_cntr_holderwith(nolock)  
  74.         WHERE  a.cntr_id = psn_cntr_holder.cntr_id  
  75.                AND psn_cntr_holder.incr_flag <> '2'  
  76.         ORDER  BY psn_cntr_holder.upd_timeDESC)               ASCONTACT_SEQ,  
  77.        CASE  
  78.          WHEN g.cntr_no IS NOT NULL THEN 1  
  79.          ELSE 0  
  80.        END                                                    ASBANK_FLAG,  
  81.        a.renew_flag                                           AS RENEW_FLAG,  
  82.        a.renew_times                                          AS RENEW_TIMES,  
  83.        '!'                                                    ASKEY_MERG_CUST_ID,  
  84.        1                                                      ASAPPL_STD_FLAG,  
  85.        a.incr_flag                                            AS INCR_FLAG,  
  86.        a.cntr_id                                              AS EXT_KEY,  
  87.        a.moneyin_type                                         ASMONEYIN_TYPE,  
  88.        a.bank_code                                            AS BANK_CODE,  
  89.        a.bank_acc_no                                          AS BANK_ACC_NO,  
  90.        a.acc_cust_name                                        AS ACC_CUST_NAME,  
  91.        a.appl_date                                            AS APPL_DATE,  
  92.        a.lose_reg_num                                         AS LOSE_NUM  
  93. FROM   tmp_f_cntr_v8_cntrrangeewith(nolock)  
  94.        INNER JOIN std_contract a WITH(nolock)  
  95.          ON a.cntr_id = e.cntr_no  
  96.        LEFT JOIN cntr_basic_statebwith(nolock)  
  97.          ON a.cntr_id = b.cntr_id  
  98.             AND b.incr_flag <> '2'  
  99.        LEFT JOIN(SELECT cntr_id,  
  100.                         Min(ipsn_cust_no)AS ipsn_cust_no,  
  101.                         Count(cntr_id)   AS ipsn_num,  
  102.                         e.PROV_BRANCH_CODE,  
  103.                         e.BATCH_NO  
  104.                  FROM   tmp_f_cntr_v8_cntrrangee WITH(nolock)  
  105.                         INNER JOIN insured WITH(nolock)  
  106.                           ON cntr_id = e.cntr_no  
  107.                  WHERE  incr_flag <> '2'  
  108.                         AND e.APP_STD_FLAG = '2'  
  109.                         AND ipsn_cust_no IS NOT NULL  
  110.                  GROUP  BY cntr_id,  
  111.                            e.PROV_BRANCH_CODE,  
  112.                            e.BATCH_NO)AS d  
  113.          ON a.cntr_id = d.cntr_id  
  114.             AND d.BATCH_NO = e.BATCH_NO  
  115.             AND d.PROV_BRANCH_CODE = e.PROV_BRANCH_CODE  
  116.        LEFT JOIN(SELECT cntr_id,  
  117.                         Sum(std_premium)      AS std_premium,  
  118.                         Sum(face_amnt)        AS face_amnt,  
  119.                         Max(stop_moneyin_date)AS stop_moneyin_date,  
  120.                         e.PROV_BRANCH_CODE,  
  121.                         e.BATCH_NO  
  122.                  FROM   tmp_f_cntr_v8_cntrrangee WITH(nolock)  
  123.                         INNER JOIN cntr_sub_state WITH(nolock)  
  124.                           ON cntr_id = e.cntr_no  
  125.                  WHERE  incr_flag <> '2'  
  126.                         AND e.APP_STD_FLAG = '2'  
  127.                  GROUP  BY cntr_id,  
  128.                            e.PROV_BRANCH_CODE,  
  129.                            e.BATCH_NO)AS z  
  130.          ON a.cntr_id = z.cntr_id  
  131.             AND z.BATCH_NO = e.BATCH_NO  
  132.             AND z.PROV_BRANCH_CODE = e.PROV_BRANCH_CODE  
  133.        LEFT JOIN(SELECT cntr_id,  
  134.                         Max(out_force_date)  AS out_force_date,  
  135.                         Max(re_in_force_date)AS re_in_force_date,  
  136.                         e.PROV_BRANCH_CODE,  
  137.                         e.BATCH_NO  
  138.                  FROM   tmp_f_cntr_v8_cntrrangee WITH(nolock)  
  139.                         INNER JOIN if_of_alt WITH(nolock)  
  140.                           ON cntr_id = e.cntr_no  
  141.                  WHERE  incr_flag <> '2'  
  142.                         AND e.APP_STD_FLAG = '2'  
  143.                  GROUP  BY cntr_id,  
  144.                            e.PROV_BRANCH_CODE,  
  145.                            e.BATCH_NO)AS f  
  146.          ON a.cntr_id = f.cntr_id  
  147.             AND f.BATCH_NO = e.BATCH_NO  
  148.             AND f.PROV_BRANCH_CODE = e.PROV_BRANCH_CODE  
  149.        LEFT JOIN(SELECT DISTINCT grant_tranlst.cntr_no,  
  150.                                  e.PROV_BRANCH_CODE,  
  151.                                  e.BATCH_NO  
  152.                  FROM   tmp_f_cntr_v8_cntrrangee WITH(nolock)  
  153.                         INNER JOIN grant_tranlst WITH(nolock)  
  154.                           ON grant_tranlst.cntr_no = e.cntr_no  
  155.                  WHERE  incr_flag <> '2'  
  156.                         AND e.APP_STD_FLAG = '2')AS g  
  157.          ON a.cntr_no = g.cntr_no  
  158.             AND g.BATCH_NO = e.BATCH_NO  
  159.             AND g.PROV_BRANCH_CODE = e.PROV_BRANCH_CODE  
  160. WHERE  a.cntr_no IS NOT NULL  
  161.        AND a.cntr_type <> 'M'  
  162.        AND a.pol_code <> '263'  
  163.        AND e.APP_STD_FLAG = '2'  
  164.        AND Isnumeric(a.renew_flag) = 1  
  165.        AND e.PROV_BRANCH_CODE = ?  
  166.        AND e.BATCH_NO = ?   

優化後:code

 
    1. SELECT a.appl_no                                              AS APPL_NO,  
    2.        a.cntr_no                                              AS CNTR_NO,  
    3.        CASE  
    4.          WHEN a.mr_type = 'M' THEN a.cntr_no  
    5.          ELSE (SELECT TOP 1 cntr_no  
    6.                FROM   std_contract WITH(nolock)  
    7.                WHERE  a.master_cntr_id = std_contract.cntr_id)  
    8.        END                                                    ASMASTER_CNTR_NO,  
    9.        a.sg_no                                                ASSG_NO,  
    10.        Ltrim(Rtrim(CONVERT(VARCHAR(6), a.mgr_branch_no)))     AS TOWN_BRANCH_CODE,  
    11.        dbo.Pub_salesno(a.n_sales_branch_no, a.n_sales_code, 8)AS KEY_SALER_ID,  
    12.        Isnull(a.n_sales_branch_no, '!')                       AS BRANCH_NO,  
    13.        Isnull(a.n_sales_code, '!')                            AS AGENT_NO,  
    14.        a.sales_channel                                        AS SALES_CHANNEL_CODE,  
    15.        '!'                                                    ASMANAGE_CHANNEL_CODE,  
    16.        '!'                                                    ASCENTER_CODE,  
    17.        a.pol_code                                             AS POL_CODE,  
    18.        CASE  
    19.          WHEN a.moneyin_itrvl = 'W' THEN 1  
    20.          ELSE b.moneyin_dur  
    21.        END                                                    ASMONEY_DUR,  
    22.        a.moneyin_itrvl                                        AS ITRVL_CODE,  
    23.        d.ipsn_cust_no                                         AS KEY_IPSN_CUST_ID,  
    24.        (SELECT TOP1 hldr_cust_no  
    25.         FROM   psn_cntr_holderWITH(nolock)  
    26.         WHERE  a.cntr_id = psn_cntr_holder.cntr_id  
    27.                AND psn_cntr_holder.incr_flag <> '2'  
    28.         ORDER  BY psn_cntr_holder.upd_time DESC)              ASKEY_HLDR_CUST_ID,  
    29.        CASE  
    30.          WHEN b.insur_dur_unit = 'W' THEN 999  
    31.          ELSE b.insur_dur  
    32.        END                                                    ASINSUR_DUR,  
    33.        a.in_force_date                                        AS IN_FORCE_DATE,  
    34.        a.sign_date                                            ASSIGN_DATE,  
    35.        a.cntr_term_date                                       AS TERM_DATE,  
    36.        CASE  
    37.          WHEN a.cg_no IS NULL THEN (SELECT TOP 1 Cast(ext_key12 AS DATETIME)  
    38.                                     FROM   insur_appl_cv_task hWITH(nolock)  
    39.                                     WHERE  a.appl_no = h.rel_key_no  
    40.                                            AND a.cntr_no = h.ext_key9  
    41.                                            AND Isdate(h.ext_key12) = 1  
    42.                                            AND h.incr_flag <> '2'  
    43.                                     ORDER  BY task_seq DESC)  
    44.          ELSE (SELECT TOP 1 Cast(ext_key12 AS DATETIME)  
    45.                FROM   insur_appl_cv_taskh WITH(nolock)  
    46.                WHERE  a.appl_no = h.rel_key_no  
    47.                       AND a.cg_no = h.ext_key9  
    48.                       AND Isdate(h.ext_key12) = 1  
    49.                       AND h.incr_flag <> '2'  
    50.                ORDER  BY task_seq DESC)  
    51.        END                                                    ASRESP_DATE,  
    52.        a.mr_type                                              AS MR_TYPE_CODE,  
    53.        a.cntr_stat                                            AS CNTR_STAT,  
    54.        a.cntr_type                                            ASCNTR_TYPE_CODE,  
    55.        8                                                      ASDATA_SRC_ID,  
    56.        z.std_premium                                          AS FACT_STD_PREM,  
    57.        z.face_amnt                                            ASFACT_FACE_AMNT,  
    58.        d.ipsn_num                                             AS FACT_IPSN_NUM,  
    59.        a.cntr_term_cause                                      AS CNTR_STOP_CODE,  
    60.        z.stop_moneyin_date                                    AS STOP_MONEYIN_DATE,  
    61.        a.cntr_expiry_date                                     AS EXPIRY_DATE,  
    62.        f.out_force_date                                       AS OUT_FORCE_DATE,  
    63.        f.re_in_force_date                                     ASRE_IN_FORCE_DATE,  
    64.        Substring(a.appl_no, 1, 4)                             AS CARD_CODE,  
    65.        CASE  
    66.          WHEN a.Sales_channelin('OA', 'SP') THEN dbo.Pub_salesno(a.n_sales_branch_no, a.n_sales_code, 8)  
    67.          ELSE '-1'  
    68.        END                                                    ASKEY_SITE_ID,  
    69.        Dateadd(day, -1, auto_in_force_date)                   ASENROLL_DATE,  
    70.        (SELECT TOP1 contact_seq  
    71.         FROM   psn_cntr_holderWITH(nolock)  
    72.         WHERE  a.cntr_id = psn_cntr_holder.cntr_id  
    73.                AND psn_cntr_holder.incr_flag <> '2'  
    74.         ORDER  BY psn_cntr_holder.upd_timeDESC)               ASCONTACT_SEQ,  
    75.        CASE  
    76.          WHEN g.cntr_no IS NOT NULL THEN 1  
    77.          ELSE 0  
    78.        END                                                    ASBANK_FLAG,  
    79.        a.renew_flag                                           AS RENEW_FLAG,  
    80.        a.renew_times                                          AS RENEW_TIMES,  
    81.        '!'                                                    ASKEY_MERG_CUST_ID,  
    82.        1                                                      ASAPPL_STD_FLAG,  
    83.        a.incr_flag                                            AS INCR_FLAG,  
    84.        a.cntr_id                                              AS EXT_KEY,  
    85.        a.moneyin_type                                         AS MONEYIN_TYPE,  
    86.        a.bank_code                                            AS BANK_CODE,  
    87.        a.bank_acc_no                                          ASBANK_ACC_NO,  
    88.        a.acc_cust_name                                        AS ACC_CUST_NAME,  
    89.        a.appl_date                                            AS APPL_DATE,  
    90.        a.lose_reg_num                                         ASLOSE_NUM  
    91. FROM   csipdb.std_contract_tmpa WITH(nolock)  
    92.        LEFT JOIN csipdb.cntr_basic_state_tmpbWITH(nolock)  
    93.          ON a.cntr_id = b.cntr_id  
    94.             AND b.incr_flag <> '2'  
    95.        LEFT JOIN(SELECT cntr_id,  
    96.                         Min(ipsn_cust_no)AS ipsn_cust_no,  
    97.                         Count(cntr_id)   AS ipsn_num  
    98.                  FROM   csipdb.insured_tmpWITH(nolock)  
    99.                  WHERE  incr_flag <> '2'  
    100.                         AND ipsn_cust_no IS NOT NULL  
    101.                  GROUP  BY cntr_id)AS d  
    102.          ON a.cntr_id = d.cntr_id  
    103.        LEFT JOIN(SELECT cntr_id,  
    104.                         Sum(std_premium)      AS std_premium,  
    105.                         Sum(face_amnt)        AS face_amnt,  
    106.                         Max(stop_moneyin_date)AS stop_moneyin_date  
    107.                  FROM   csipdb.cntr_sub_state_tmpWITH(nolock)  
    108.                  WHERE  incr_flag <> '2'  
    109.                  GROUP  BY cntr_id)AS z  
    110.          ON a.cntr_id = z.cntr_id  
    111.        LEFT JOIN(SELECT cntr_id,  
    112.                         Max(out_force_date)  AS out_force_date,  
    113.                         Max(re_in_force_date)AS re_in_force_date  
    114.                  FROM   csipdb.if_of_alt_tmpWITH(nolock)  
    115.                  WHERE  incr_flag <> '2'  
    116.                  GROUP  BY cntr_id)AS f  
    117.          ON a.cntr_id = f.cntr_id  
    118.        LEFT JOIN(SELECT DISTINCT cntr_no  
    119.                  FROM   csipdb.grant_tranlst_tmp WITH(nolock)  
    120.                  WHERE  incr_flag <> '2')AS g  
    121.          ON a.cntr_no = g.cntr_no  
    122. WHERE  a.cntr_no IS NOT NULL  
    123.        AND a.cntr_type <> 'M'  
    124.        AND a.pol_code <> '263'  
    125.        AND Isnumeric(a.renew_flag) = 1  
相關文章
相關標籤/搜索