七郎's JavaBlog

          草木竹石皆可為劒。至人之用人若鏡,不將不迎,應而不藏,故能勝物而不傷。
          posts - 60, comments - 14, trackbacks - 0, articles - 0
          select count(distinct v_yjhm)
            from (select v_yjhm
                    from zjjk_t_yssj_o_his a
                   where n_yjzl > 0
                     and d_sjrq between to_date('20070301', 'yyyymmdd') and
                         to_date('20070401', 'yyyymmdd')
                     and v_yjzldm like '40%'
                     and not exists(select 'a' from INST_TRIG_ZJJK_T_YSSJ_O b where a.v_yjtm=b.yjbh)
                     --and v_yjtm not in (select yjbh from INST_TRIG_ZJJK_T_YSSJ_O)
                  union
                  select v_yjhm
                    from zjjk_t_yssj_u_his a
                   where n_yjzl > 0
                     and d_sjrq between to_date('20070301', 'yyyymmdd') and
                         to_date('20070401', 'yyyymmdd')
                     and v_yjzldm like '40%'
                     and not exists(select 'a' from INST_TRIG_ZJJK_T_YSSJ_U b where a.v_yjtm=b.yjbh))
                     --and v_yjtm not in (select yjbh from INST_TRIG_ZJJK_T_YSSJ_U))
           
          說明:1、zjjk_t_yssj_o_his 、zjjk_t_yssj_u_his  的d_sjrq 上都有一個索引了
                   2、zjjk_t_yssj_o_his 、zjjk_t_yssj_u_his   的v_yjtm 都為 not null 字段
                  3、INST_TRIG_ZJJK_T_YSSJ_O、INST_TRIG_ZJJK_T_YSSJ_U 的 yjbh 為PK
               
          優化建議:
          1、什么是DISTINCT ?   就是分組排序后取唯一值   ,底層行為  分組排序
          2、什么是 UNION 、 UNION ALL  ?  UNION : 對多個結果集取DISTINCT ,生成一個不含重復記錄的結果集,返回給前端,UNION ALL :不對結果集進行去重復操作     底層行為:分組排序
          3、什么是 COUNT(*)   ?   累加
          4、需要有什么樣的索引?   S_sjrq + v_yjzldm  : 理由: 假如全省的數據量在表中全部數為1000萬,查詢月數據量為200萬,1000萬中特快占50%, 則 通過 beween 時間(d_sjrq)+ 種類( v_yjzldm ),可過濾出約100萬,這是最好的檢索方式了。
          5、兩表都要進行一次 NOT EXISTS 運算,如何做最優?   NOT EXISTS 是不好做的運算,但是我們可以合并兩次的NOT EXISTS 運算。讓這費資源的活只干一次。
           
          綜合以上,我們可以如下優化這個SQL:
            1、內部的UNION 也是去重復,外部的DISTINCT 也是去重復,可左右去掉一個,建議內部的改為 UNION ALL , 這里稍請注意一下,如果V_YJHM 有NULL的情況,可能會引起COUNT值不對實際數的情況。
            2、建一個 D_SJRQ+V_YJZLDM 的復合索引
            3、將兩個子查詢先 UNION ALL 聯結 , 另兩個用來做 NOT EXISTS 的表也 UNION ALL  聯結
            4、在3的基礎上再做 NOT EXISTS
            5、將NOT EXISTS 替換為NOT IN ,同時加提示 HASH_AJ 做半連接HASH運算
            6、最后為外層的COUNT(DISTINCT … 獲得結果數
           
           
          SQL書寫如下:
          select count(distinct v_yjhm)
            from (select v_yjtm, v_yjhm
                    from zjjk_t_yssj_o_his a
                   where n_yjzl > 0
                     and d_sjrq between to_date('20070301', 'yyyymmdd') and
                         to_date('20070401', 'yyyymmdd')
                     and v_yjzldm like '40%'
                  union all
                  select v_yjtm, v_yjhm
                    from zjjk_t_yssj_u_his a
                   where n_yjzl > 0
                     and d_sjrq between to_date('20070301', 'yyyymmdd') and
                         to_date('20070401', 'yyyymmdd')
                     and v_yjzldm like '40%'
                  ) a
           where a.v_yjtm not IN
                 (select /*+ HASH_AJ */
                   yjbh
                    from (select yjbh
                            from INST_TRIG_ZJJK_T_YSSJ_O
                          union all
                          select yjbh from INST_TRIG_ZJJK_T_YSSJ_U))

          經過上述改造,原來這個SQL的執行時間如果為2分鐘的話,現在應該20秒足夠!

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 红河县| 易门县| 商河县| 内黄县| 临沭县| 嘉义县| 和田市| 沙坪坝区| 新巴尔虎左旗| 大埔县| 基隆市| 通辽市| 朝阳县| 突泉县| 娄烦县| 轮台县| 怀仁县| 伊金霍洛旗| 鱼台县| 宁陵县| 通化县| 广宗县| 铜川市| 连州市| 上思县| 旬阳县| 彭泽县| 晋城| 灵宝市| 右玉县| 古蔺县| 萝北县| 都江堰市| 额尔古纳市| 崇信县| 连城县| 乌鲁木齐县| 七台河市| 灵川县| 临桂县| 三穗县|