我正在尝试根据应用列的函数的结果创建索引,我必须提取一个数字。
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;
但似乎并不重要。
答案 0 :(得分:3)
要创建确定性函数,请在返回类型声明旁边使用DETERMINISTIC
子句,
请参阅语法here。
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:
答案 1 :(得分: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
如您所见,使用了索引。