2013-07-16 3 views
0

숫자를 추출해야하는 열을 적용한 함수 결과를 기반으로 인덱스를 만들려고합니다. 나는이 쿼리를 실행할 때결정적 함수를 만드는 방법은 무엇입니까?

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을 반환하기 때문에 인덱스가 결정 적이라고 생각하지만 표현식이 너무 복잡하여 사용할 수 있는지 여부는 알 수 없습니다. 또한 코드를 함수로 이동하려고 시도했지만 동일합니다. 나는 열쇠가이 결정 론적 일 (내가 잘못하고있는 거라고 생각해?) 및/또는 원래 열에 null 값을 갖는 테이블을 믿습니다. 색인이 사용된다는 것을 어떻게 확신 할 수 있습니까? 이 기능입니다 : 나는이

ANALYZE TABLE my_table COMPUTE STATISTICS; 

을 실행

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; 

그러나 중요하지 않는 것 같습니다.

답변

3

결정적 함수를 만들려면 구문 here을 참조하십시오. 반환 형식 선언 옆에 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 

그래서 오라클은이 색인에이 색인을 사용할 수 없습니다. 에리,이 표현은 다릅니다. 또한 ANALYZE TABLE를 사용하지 않는이,이 명령은 10g 사용되지 않습니다, 대신 DBMS_STATS를 사용

+0

안녕하세요, "parametros"의 경우 "my_column"을 사용하여 여기에 예제를 작성하는 것을 잊어 버렸습니다. 실제로 동일한 함수로 테스트했지만 인덱스는 사용되지 않았습니다. 내 함수에 대한 결정 론적 절로 테스트 할 것이지만 쿼리와 함께 작동해야합니다. 맞습니까? – Roger

2

기능 기반 인덱스를 사용하려면 당신이해야 :

  • 사용 자신의 기능에 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 

을 사용됩니다.

관련 문제