1. 程式人生 > >oracle索引失效的情況已經oracle的一些隱式轉換

oracle索引失效的情況已經oracle的一些隱式轉換

      容易引起oracle索引失效的原因很多:

      1、在索引列上使用函式。如SUBSTR,DECODE,INSTR等,對索引列進行運算.需要建立函式索引就可以解決了。

  2、新建的表還沒來得及生成統計資訊,分析一下就好了

  3、基於cost的成本分析,訪問的表過小,使用全表掃描的消耗小於使用索引。

  4、使用<>、not in 、not exist,對於這三種情況大多數情況下認為結果集很大,一般大於5%-15%就不走索引而走FTS。

  5、單獨的>、<。

  6、like "%_" 百分號在前。

  7、單獨引用複合索引裡非第一位置的索引列。

  8、字元型欄位為數字時在where條件裡不新增引號。

  9、當變數採用的是times變數,而表的欄位採用的是date變數時.或相反情況。

  10、索引失效,可以考慮重建索引,rebuild online。

  11、B-tree索引 is null不會走,is not null會走,點陣圖索引 is null,is not null  都會走、聯合索引 is not null 只要在建立的索引列(不分先後)都會走。

Oracle中對不同型別的處理具有顯式型別轉換(Explicit)和隱式型別轉換(Implicit)兩種方式,對於顯式型別轉換,我們是可控的,但是對於隱式型別轉換,當然不建議使用

,
因為很難控制,有不少缺點,但是我們很難避免碰到隱式型別轉換,如果不瞭解隱式型別轉換的規則,那麼往往會改變我們SQL的執行計劃,從而可能導致效率降低或其它問題。

在oracle中,如果不同的資料型別之間關聯,如果不顯式轉換資料,則它會根據以下規則對資料進行隱式轉換

1) 對於INSERT和UPDATE操作,oracle會把插入值或者更新值隱式轉換為欄位的資料型別。

   假如id列的資料型別為number

   update t set id='1'; -> 相當於 update t set id=to_number('1');

   insert into t(id) values('1') -> insert into t values(to_number('1'));

2) 對於SELECT語句,oracle會把欄位的資料型別隱式轉換為變數的資料型別。
   如假設id列的資料型別為varchar2

   select * from t where id=1; -> select * from t where to_number(id)=1;

   但如果id列的資料型別為number,則

   select * from t where id='1'; -> select * from t where id=to_number('1');(參考下文)

3) 當比較一個字元型和數值型的值時,oracle會把字元型的值隱式轉換為數值型。

    如假設id列的資料型別為number

    select * from t where id='1'; -> select * from t where id=to_number('1');

4) 當比較字元型和日期型的資料時,oracle會把字元型轉換為日期型。

    如假設create_date為字元型,

    select * from t where create_date>sysdate; -> select * from t where to_date(create_date)>sysdate;(注意,此時session的nls_date_format需要與字串格式相符)

    假設create_date為date型,

    select * from t where create_date>'2006-11-11 11:11:11'; -> select * from t where   create_date>to_date('2006-11-11 11:11:11'); (注意,此時session的nls_date_format需要與字串格式相符)

5) 如果呼叫函式或過程等時,如果輸入引數的資料型別與函式或者過程定義的引數資料型別不一直,則oracle會把輸入引數的資料型別轉換為函式或者過程定義的資料型別。

   如假設過程如下定義 p(p_1 number)

   exec p('1'); -> exec p(to_number('1')); 6)

   賦值時,oracle會把等號右邊的資料型別轉換為左邊的資料型別。

   如 var a number a:='1'; - > a:=to_number('1');

7) 用連線操作符(||)時,oracle會把非字元型別的資料轉換為字元型別。

    select 1||'2' from dual; -> select to_char(1)||'2' from dual;

8) 如果字元型別的資料和非字元型別的資料(如number、date、rowid等)作算術運算,則oracle會將字元型別的資料轉換為合適的資料型別,這些資料型別可能是number、date、rowid等。

    如果CHAR/VARCHAR2 和NCHAR/NVARCHAR2之間作算術運算,

    則oracle會將她們都轉換為number型別的資料再做比較。

9) 比較CHAR/VARCHAR2 和NCHAR/NVARCHAR2時,如果兩者字符集不一樣,則預設的轉換方式是將資料編碼從資料庫字符集轉換為國家字符集。

簡單總結:

比較時,一般是字元型轉換為數值型,字元型轉換為日期型

算術運算時,一般把字元型轉換為數值型,字元型轉換為日期型

連線時(||),一般是把數值型轉換為字元型,日期型轉換為字元型

賦值、呼叫函式時,以定義的變數型別為準。