1

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

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) IS NOT 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;

但这似乎无关紧要。

4

2 回答 2

4

要创建确定性函数,DETERMINISTIC请在返回类型声明旁边使用子句,请参见此处的语法。

create or replace function extraer_doc_id(viParam VARCHAR2) 
  return varchar2 
  DETERMINISTIC
is
begin
  RETURN replace(regexp_substr(viParam, '&idDocunet=\d+'), 'idDocunet=', NULL);
end extraer_doc_id;

您创建了一个引用my_column字段的基于函数的索引:

replace(regexp_substr(**my_column**, '&idDocunet=\d+'), 'idDocunet=', NULL)

但是在where查询的子句中,您使用的函数不同于索引中的函数(不同的列):

WHERE replace(regexp_substr(**parametros**, '&idDocunet=\d+'), 'idDocunet=', NULL) = 799493

所以 Oracle 不能在这个查询中使用这个索引,这些表达式是不同的。也不要使用ANALYZE TABLE,此命令在 10g 中已弃用,请改用DBMS_STATS

于 2013-07-16T23:17:11.157 回答
3

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

  • 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 

如您所见,使用了索引。

于 2013-07-16T23:42:25.223 回答