ORACLE 查詢不走索引的原因分析,解決辦法通過強制索引或動態執行SQL語句提高查詢速度


(一)索引失效的原因分析:

  • <>或者單獨的>,<,(有時會用到,有時不會)
  • 有時間范圍查詢;oracle 時間條件值范圍越大就不走索引
  • like "%_" 百分號在前.
  • 表沒分析(統計信息最好定期收集,以業務的不同確定不同的收集周期,在新增的索引有可能沒有收集 ,那么就會導致索引失效)
  • NVARCHAR查詢不會走索引。

  解決方法:

    分析方法有一下幾種:
    analyze table t1 compute statistics fortable; --針對表收集信息

    analyze table t2 compute statistics for allcolumns; --針對表字段收集信息

    analyze table t3 compute statistics for all indexescolumns; --收集索引字段信息

    analyze table t4 computestatistics;       --收集表,表字段,索引信息

    analyze table t5 compute statistics for allindexes;         --收集索引信息

    analyze table t6 compute statistics for table for all indexesfor allcolumns;   --

    --收集表,索引,表字段信息

  • 單獨引用復合索引里非第一位置的索引列.
  • 字符型字段為數字時在where條件里不添加引號.
  • 對索引列進行運算.需要建立函數索引.
  • not in ,not exist.
  • 當變量采用的是times變量,而表的字段采用的是date變量時.或相反情況。
  • 索引失效。
  • 基於cost成本分析(Oracle因為走全表成本會更小):查詢小表,或者返回值大概在10%以上;

  解決辦法:

    在這種條件下 oracle會認為索引更占資源,就默認不走索引了。這種情況如果覺得索引快的,通過強制索引提高查詢速度 

     select   /*+INDEX(t IDEX_HZYB_JSJL_BDJSRQ)*/   from hzyb_jsjl t
     where BDJSRQ >TO_DATE('','');
    其中T是 表名   IDEX_HZYB_JSJL_BDJSRQ 是表的索引

  • 有時都考慮到了 但就是不走索引,drop了從建試試在
  • B-tree索引 is null不會走,is not null會走,(B樹索引示例:create index random_empno_idx on test_random(empno);)
  • 位圖索引 is null,is not null   都會走(位圖索引示例:create bitmap index normal_empno_bmx on test_normal(empno);)
  • 聯合索引 is not null 只要在建立的索引列(不分先后)都會走,(組合索引示例:SQL> create index indx_t on t(object_type,object_name);) 

in null時   必須要和建立索引第一列一起使用,當建立索引第一位置條件是is null 時,其他建立索引的列可以是is null(但必須在所有列都滿足is null的時候),或者=一個值;
當建立索引的第一位置是=一個值時,其他索引列可以是任何情況(包括is null =一個值),以上兩種情況索引都會走。其他情況不會走。

 

(二)通過動態執行SQL提高查詢COUNT()執行速度

 

 1 var_strquery1 := 'SELECT COUNT(1)';
 2       var_strquery := 'FROM r_sn_link k
 3                       LEFT JOIN mfworkstatus s
 4                         ON k.p_sn = s.sysserialno
 5                       LEFT JOIN mfworkorder r
 6                         ON k.wo = r.workorderno
 7                      WHERE 1 = 1 ';
 8 
 9       IF var_smt_wo IS NOT NULL OR var_smt_wo <> ''
10       THEN
11          var_strquery := var_strquery || ' AND k.wo =''' || var_smt_wo || '''';
12       END IF;
13 
14       IF var_dip_wo IS NOT NULL OR var_dip_wo <> ''
15       THEN
16          var_strquery :=
17             var_strquery || ' AND s.workorderno =''' || var_dip_wo || '''';
18       END IF;
19 
20       IF var_skuno IS NOT NULL OR var_skuno <> ''
21       THEN
22          var_strquery :=
23                var_strquery
24             || ' AND (r.skuno ='''
25             || var_skuno
26             || ''''
27             || 'OR s.skuno ='''
28             || var_skuno
29             || ''''
30             || ')';
31       END IF;
32 
33       IF var_sn_code IS NOT NULL OR var_sn_code <> ''
34       THEN
35          var_strquery :=
36             var_strquery || ' AND k.sn_code = ''' || var_sn_code || '''';
37       END IF;
38 
39       IF var_p_sn IS NOT NULL OR var_p_sn <> ''
40       THEN
41          var_strquery := var_strquery || 'AND k.p_sn =''' || var_p_sn || '''';
42       END IF;
43 
44       IF var_from_datetime IS NOT NULL OR var_from_datetime <> ''
45       THEN
46          var_strquery :=
47                var_strquery
48             || ' AND k.work_time >= to_date('
49             || var_from_datetime
50             || ',''yyyy/mm/dd hh24:mi:ss'')';
51       END IF;
52 
53       IF var_to_datetime IS NOT NULL OR var_to_datetime <> ''
54       THEN
55          var_strquery :=
56                var_strquery
57             || ' AND k.work_time <= to_date('
58             || var_to_datetime
59             || ',''yyyy/mm/dd hh24:mi:ss'')';
60       END IF;
61 
62       --動態執行查詢語句返回記錄數
63       EXECUTE IMMEDIATE var_strquery1 || var_strquery INTO var_rowcount;

 


免責聲明!

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



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