函式索引使用細節——自定義函式的索引化
在筆者之前的Blog中,已經多次對函式索引Functional Index進行介紹。其中包括函式索引的原理、使用和應用場景。針對兩個使用細節,補充一下其他知識內容。
函式索引可以解決一些由於SQL書寫和資料庫設計帶來的最佳化問題。我們通常使用的也是一些Oracle預定義的函式功能,那麼我們是否可以對自定義函式也加函式索引呢?
首先還是對環境的準備:
SQL> desc t
Name Type Nullable Default Comments
-------------- ------------- -------- ------- --------
OWNER VARCHAR2(30) Y
OBJECT_NAME VARCHAR2(128) Y
SUBOBJECT_NAME VARCHAR2(30) Y
OBJECT_ID NUMBER Y
(篇幅原因,有省略…)
此時,我們建立一個簡單的自定義函式f_define_nc。
SQL> create or replace function f_define_nc
2 (inpstr in varchar2)
3 return varchar2 is
4 Result varchar2(10);
5 begin
6 Result := substr(inpstr,1,5);
7 return(Result);
8 end f_define_nc;
9 /
Function created
對資料表T的列object_name加函式索引處理。
SQL> create index idx_t_fobjname on t(f_define_nc(object_name));
create index idx_t_fobjname on t(f_define_nc(object_name))
ORA-30553: 函式不能確定
檢查30553錯誤資訊。
[oracle@bspdev ~]$ oerr ora 30553
30553, 00000, "The function is not deterministic"
// *Cause: The function on which the index is defined is not deterministic
// *Action: If the function is deterministic, mark it DETERMINISTIC. If it
// is not deterministic (it depends on package state, database state,
// current time, or anything other than the function inputs) then
// do not create the index. The values returned by a deterministic
// function should not change even when the function is rewritten or
// recompiled.
簡單的說,Oracle不允許對所謂“非確定性的函式”建立函式索引。那麼,什麼是非確定性函式呢?
一個函式,無論有無引數,對相同的輸入函式都能獲得相同的輸出,我們稱之為確定性“Deterministic”函式。否則是非確定性函式。例如substr函式,就是一個確定性函式。sysdate就是一個非確定性函式。
要對一個自定義函式建立函式索引,要保證該函式是一個確定性函式,就需要使用deterministic進行標註才行。
SQL> create or replace function f_define_nc
2 (inpstr in varchar2)
3 return varchar2
4 DETERMINISTIC
5 is
6 Result varchar2(10);
7 begin
8 Result := substr(inpstr,1,5);
9 return(Result);
10 end f_define_nc;
11 /
Function created
此時,我們再次建立函式索引。
//建立函式索引
SQL> create index idx_t_fobjname on t(f_define_nc(object_name));
Index created
//收集統計量
SQL> exec dbms_stats.gather_table_stats(user,'T',cascade => true);
PL/SQL procedure successfully completed
//生成執行計劃
SQL> explain plan for select * from t where f_define_nc(object_name)='I_IND';
Explained.
SQL> select * from table(dbms_xplan.display(format=>'advanced'));
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------
Plan hash value: 669064648
----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 412 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 4 | 412 | 3 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IDX_T_FOBJNAME | 4 | | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------
這樣,我們成功的建立了函式索引。
下面,有兩個問題需要進行思考:
其一,為什麼Oracle要求函式是一個確定性的函式,才能建立函式索引。這個問題需要從函式索引的原理入手。函式索引是一種普通索引變種,Oracle在資料表中新增一個冗餘列,將函式處理的結果儲存在這個冗餘列中。之後在對這個冗餘列進行普通索引的建立。函式處理值都是儲存在索引的葉子節點中。
如果函式是一個不確定性的函式,這樣儲存在冗餘列和索引葉子節點上的檢索鍵也就失去了意義。函式索引檢索結果就是錯誤的。
其二,就是函式確定性宣告方式。只透過一個deterministic關鍵字進行宣告,就可以建立。這樣真的沒有問題嗎?我們進行下列實驗:
//定義一個典型的不確定性函式;
SQL> create or replace function f_test_nc(i_vc_word in varchar2)
2 return number
3 DETERMINISTIC
4 is
5 Result number;
6 begin
7 result := length(i_vc_word)+100*dbms_random.value;
8 return(Result);
9 end f_test_nc;
10 /
Function created
使用dbms_random函式,必然結果是不確定性的。
SQL> select f_test_nc('df') from dual;
F_TEST_NC('DF')
--------------------------------------------------------------------------------
15.648738643901598708753466833273910001
SQL> select f_test_nc('df') from dual;
F_TEST_NC('DF')
--------------------------------------------------------------------------------
52.17432021982655792498049873516166188
SQL> select f_test_nc('df') from dual;
F_TEST_NC('DF')
--------------------------------------------------------------------------------
30.245275513714721819304937071210704424
新增在函式索引中呢?
//成功建立索引
SQL> create index idx_t_supname on t(f_test_nc(object_name));
Index created
SQL> explain plan for select * from t where f_test_nc(object_name)=10;
Explained
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1966470384
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 98 | 2 (0
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 98 | 2 (0
|* 2 | INDEX RANGE SCAN | IDX_T_SUPNAME | 1 | | 1 (0
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("SYS"."F_TEST_NC"("OBJECT_NAME")=10)
14 rows selected
可見,只要宣告瞭deterministic關鍵字在函式中。Oracle就認為函式的定義者會去保證函式自身的確定性,就不去進行其他驗證。一旦建立函式索引,進行查詢的時候也會使用到。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/17203031/viewspace-698041/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 函式索引的使用細節——常數表示式函式索引
- 自定義函式索引使用及其注意點函式索引
- SQL優化案例-自定義函式索引(五)SQL優化函式索引
- Oracle優化案例-自定義函式索引(五)Oracle優化函式索引
- SQL最佳化案例-自定義函式索引(五)SQL函式索引
- 索引中使用函式索引函式
- SQL優化--函式索引SQL優化函式索引
- 函式索引陷阱函式索引
- oracle函式索引Oracle函式索引
- MySQL函式索引及優化MySql函式索引優化
- 基於函式的索引函式索引
- 函式索引的問題函式索引
- 函式索引的儲存函式索引
- Oracle之函式索引Oracle函式索引
- 說說函式索引函式索引
- 複合索引與函式索引優化一例索引函式優化
- Hive常用函式及自定義函式Hive函式
- 基於函式的索引狀態變化函式索引
- Oracle基於函式的索引Oracle函式索引
- deterministic function 函式索引Function函式索引
- sequence 和索引函式呼叫索引函式
- shell自定義函式函式
- Oracle 自定義函式Oracle函式
- perl自定義函式函式
- Hive函式(內建函式+自定義標準函式UDF)Hive函式
- 動畫函式的繪製及自定義動畫函式動畫函式
- OCP之基於函式的索引函式索引
- 關於函式索引的問題?函式索引
- Oracle索引梳理系列(六)- Oracle索引種類之函式索引Oracle索引函式
- 索引ROWID轉換函式索引函式
- [20120612]函式索引中使用substr函式.txt函式索引
- SQL優化中索引列使用函式之靈異事件SQL優化索引函式事件
- PHP 自定義函式用法及常用函式集合PHP函式
- java自定義equals函式和hashCode函式Java函式
- mysql 自定義分析函式 least 及 日期函式MySql函式AST
- GRDB自定義的純函式函式
- HIVE中的自定義函式Hive函式
- hive 3.0.0自定義函式Hive函式