Oracle 如何制作确定性函数?

Oracle 如何制作确定性函数?,oracle,oracle10g,indexing,deterministic,Oracle,Oracle10g,Indexing,Deterministic,我正在尝试根据一个函数的结果创建一个索引,该函数应用于一个列,在该列中我必须提取一个数字 Example String: ...someText...&idDocunet=799493...someText... [799493] <- Note the number The function: replace(regexp_substr(parametros, '&idDocunet=\d+'), 'idD

我正在尝试根据一个函数的结果创建一个索引,该函数应用于一个列,在该列中我必须提取一个数字

Example String: ...someText...&idDocunet=799493...someText...
                                 [799493] <- Note the number
The function: replace(regexp_substr(parametros, '&idDocunet=\d+'), 'idDocunet=', NULL)
The index: create index example on MY_TABLE (replace(regexp_substr(parametros, '&idDocunet=\d+'), 'idDocunet=', NULL));
还是这个

SELECT *
FROM my_table
WHERE replace(regexp_substr(parametros, '&idDocunet=\d+'), 'idDocunet=', NULL) = 799493
或者加入

不使用索引,它每次都执行完整表扫描。我相信索引是确定性的,因为它总是返回数字,或者null,但我不知道表达式是否太复杂,无法使用。我还尝试将代码移动到函数中,但结果是一样的。我相信关键在于这个确定性的东西(我做错了吗?)和/或原始列上有空值的表。如何确保使用索引?这就是功能:

create or replace function extraer_doc_id(viParam VARCHAR2) return varchar2 is
begin
  RETURN replace(regexp_substr(viParam, '&idDocunet=\d+'), 'idDocunet=', NULL);
end extraer_doc_id;
我也执行了这个

ANALYZE TABLE my_table COMPUTE STATISTICS;

但这似乎无关紧要。

要创建确定性函数,请在返回类型声明旁边使用
deterministic
子句, 请参阅语法

您创建了一个基于函数的索引,该索引引用了my_列字段:

replace(regexp_substr(**my_column**, '&idDocunet=\d+'), 'idDocunet=', NULL)
但是在查询的
where
子句中,您使用的函数与索引中的函数不同(不同列):

因此Oracle无法将此索引用于此查询,因为这些表达式不同。
也不要使用
ANALYZE TABLE
,此命令在10g中已被弃用,请改用:

要创建确定性函数,请在返回类型声明旁边使用
deterministic
子句, 请参阅语法

您创建了一个基于函数的索引,该索引引用了my_列字段:

replace(regexp_substr(**my_column**, '&idDocunet=\d+'), 'idDocunet=', NULL)
但是在查询的
where
子句中,您使用的函数与索引中的函数不同(不同列):

因此Oracle无法将此索引用于此查询,因为这些表达式不同。
也不要使用
ANALYZE TABLE
,此命令在10g中已被弃用,请改用:

要使用基于函数的索引,您应该:

  • 在自己的函数中使用
    DETERMINISTIC
    子句
  • 查询必须使用与您提到的创建索引相同的函数和列
例如:

set define off
drop table test;
create table test ( s varchar2( 100 ) )
/

create or replace function getDocId( p varchar2 )
return number
deterministic
is
begin
  return to_number( regexp_replace(p, '^.*&idDocunet=(\d+).*$', '\1') );
end getDocId;
/

create index test_fbi on test( getDocId( s ) )
/

insert into test values( '...someText...&idDocunet=799493...someText...' )
/
现在让我们制定一个计划:

explain plan for
select * 
  from test
 where getdocid( s ) = 1
/

select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT                                                                                                                                                                                                                                                                                          
---------------------------------------------------------------------------------------
Plan hash value: 3113607502                                                                                                                                                                                                                                                                                  

----------------------------------------------------------------------------------------                                                                                                                                                                                                                     
| Id  | Operation                   | Name     | Rows  | Bytes | Cost (%CPU)| Time     |                                                                                                                                                                                                                     
----------------------------------------------------------------------------------------                                                                                                                                                                                                                     
|   0 | SELECT STATEMENT            |          |     1 |    65 |     1   (0)| 00:00:01 |                                                                                                                                                                                                                     
|   1 |  TABLE ACCESS BY INDEX ROWID| TEST     |     1 |    65 |     1   (0)| 00:00:01 |                                                                                                                                                                                                                     
|*  2 |   INDEX RANGE SCAN          | TEST_FBI |     1 |       |     1   (0)| 00:00:01 |                                                                                                                                                                                                                     
----------------------------------------------------------------------------------------                                                                                                                                                                                                                     

Predicate Information (identified by operation id):                                                                                                                                                                                                                                                          
---------------------------------------------------                                                                                                                                                                                                                                                          

   2 - access("TEST"."GETDOCID"("S")=1)                                                                                                                                                                                                                                                                      

Note                                                                                                                                                                                                                                                                                                         
-----                                                                                                                                                                                                                                                                                                        
   - dynamic sampling used for this statement (level=2)                                                                                                                                                                                                                                                      

 18 rows selected 

如您所见,使用了索引。

要使用基于函数的索引,您应该:

  • 在自己的函数中使用
    DETERMINISTIC
    子句
  • 查询必须使用与您提到的创建索引相同的函数和列
例如:

set define off
drop table test;
create table test ( s varchar2( 100 ) )
/

create or replace function getDocId( p varchar2 )
return number
deterministic
is
begin
  return to_number( regexp_replace(p, '^.*&idDocunet=(\d+).*$', '\1') );
end getDocId;
/

create index test_fbi on test( getDocId( s ) )
/

insert into test values( '...someText...&idDocunet=799493...someText...' )
/
现在让我们制定一个计划:

explain plan for
select * 
  from test
 where getdocid( s ) = 1
/

select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT                                                                                                                                                                                                                                                                                          
---------------------------------------------------------------------------------------
Plan hash value: 3113607502                                                                                                                                                                                                                                                                                  

----------------------------------------------------------------------------------------                                                                                                                                                                                                                     
| Id  | Operation                   | Name     | Rows  | Bytes | Cost (%CPU)| Time     |                                                                                                                                                                                                                     
----------------------------------------------------------------------------------------                                                                                                                                                                                                                     
|   0 | SELECT STATEMENT            |          |     1 |    65 |     1   (0)| 00:00:01 |                                                                                                                                                                                                                     
|   1 |  TABLE ACCESS BY INDEX ROWID| TEST     |     1 |    65 |     1   (0)| 00:00:01 |                                                                                                                                                                                                                     
|*  2 |   INDEX RANGE SCAN          | TEST_FBI |     1 |       |     1   (0)| 00:00:01 |                                                                                                                                                                                                                     
----------------------------------------------------------------------------------------                                                                                                                                                                                                                     

Predicate Information (identified by operation id):                                                                                                                                                                                                                                                          
---------------------------------------------------                                                                                                                                                                                                                                                          

   2 - access("TEST"."GETDOCID"("S")=1)                                                                                                                                                                                                                                                                      

Note                                                                                                                                                                                                                                                                                                         
-----                                                                                                                                                                                                                                                                                                        
   - dynamic sampling used for this statement (level=2)                                                                                                                                                                                                                                                      

 18 rows selected 
正如您所看到的,使用了索引。

Hi,对于“parametros”这件事,当我在这里用“my_column”编写示例时,我忘记了更新它,我确实使用了相同的函数进行了测试,但没有使用索引。我将在我的函数中使用deterministic子句来测试它,但它应该与查询一起工作,对吗?嗨,对于“parametros”这件事,我只是忘记了更新示例,当我在这里用“my_column”编写它时,我确实使用了相同的函数进行了测试,但没有使用索引。我将在我的函数中使用deterministic子句测试它,但它应该与查询一起工作,对吗?