隨筆-1  評論-0  文章-0  trackbacks-0

          [Oracle性能模式] 查找某個號碼是否在號碼段列表中之性能模式(2011.04.30)
          【應(yīng)用場景】
              表test每行保存一個號碼段(hm0, hm1),不同記錄的號碼段不會出現(xiàn)交叉。需高效地判斷出某個號碼是否出現(xiàn)在某個號碼段中。

          -- 建測試表
          create table test (
            hm0 number(8) not null, -- 號碼起
            hm1 number(8) not null -- 號碼止
          );


          -- 插入2萬條數(shù)據(jù)
          begin
            for i in 1..20000 loop
              insert into test values(i*100, i*100+10); -- hm0間隔100,每段10個號碼,故不會交叉
            end loop;
          end;
          /
          commit;

          -- 建索引
          create index i_test_1 on test(hm0, hm1);
          【低效模式】
          -- 查找號碼 2000006 是否在號碼段列表中
          select * from test a
            where a.hm0 <= 2000006 and a.hm1>= 2000006
          ;
                 HM0        HM1
          ---------- ----------
             2000000    2000010

          -- 注意查詢計劃中的 Search columns=1; 低效的原因在于Oracle會判斷 hm0 <= 2000006 的每條記錄是否滿足全部where條件
          SELECT STATEMENT, GOAL = CHOOSE      
           INDEX RANGE SCAN Object owner=SCOTT Object name=I_TEST_1    Search columns=1

          Statistics
          ----------------------------------------------------------
                    0  recursive calls
                    0  db block gets
                   54  consistent gets   -- 記錄數(shù)增多時,該值會加大
            
          【重構(gòu)方案】
          -- 前提:
          -- 1. 需在 hm0 上建一 desc 索引
          -- 2. 利用 rownum<... 特性,讓Oracle找到第一條記錄即停止掃描
          create index i_test_2 on test(hm0 desc);
          -- 利用表本身語義決定的號碼段不會交叉的特性,這些Oracle優(yōu)化器是不會知道的; index hint似乎不能少,否則Oracle不會自動走這個索引
          select * from(
            select /*+ index(a i_test_2) */ * from test a
              where a.hm0 <= 2000006
              order by a.hm0 desc) b
            where rownum<2 and b.hm1 >= 2000006;

                 HM0        HM1
          ---------- ----------
             2000000    2000010

          Execution Plan
          ----------------------------------------------------------
             0      SELECT STATEMENT Optimizer=CHOOSE (Cost=3 Card=1 Bytes=26)
             1    0   COUNT (STOPKEY)
             2    1     VIEW (Cost=3 Card=1 Bytes=26)
             3    2       TABLE ACCESS (BY INDEX ROWID) OF 'TEST' (Cost=3 Card=1
                     Bytes=26)

             4    3         INDEX (RANGE SCAN) OF 'I_TEST_2' (NON-UNIQUE) (Cost=
                    2 Card=2)

          Statistics
          ----------------------------------------------------------
                    0  recursive calls
                    0  db block gets
                    3  consistent gets

          -- 結(jié)束測試刪表
          drop table test;
           
          perl5原創(chuàng)@20110430

          posted on 2011-04-30 16:01 十次突擊 閱讀(157) 評論(0)  編輯  收藏

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


          網(wǎng)站導(dǎo)航:
           
          <2011年4月>
          272829303112
          3456789
          10111213141516
          17181920212223
          24252627282930
          1234567

          常用鏈接

          留言簿

          隨筆檔案

          搜索

          •  

          最新評論

          主站蜘蛛池模板: 株洲县| 玉门市| 郧西县| 保康县| 义马市| 深州市| 武鸣县| 赤峰市| 德保县| 孟连| 唐海县| 德兴市| 阳东县| 铜梁县| 腾冲县| 永福县| 金溪县| 德安县| 凤城市| 观塘区| 永昌县| 鄂州市| 沧州市| 仪陇县| 武义县| 呼玛县| 赫章县| 诏安县| 专栏| 老河口市| 诸城市| 五家渠市| 郁南县| 华池县| 巴林右旗| 天台县| 资兴市| 曲靖市| 萨迦县| 平塘县| 玛曲县|