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を返すため、決定論的であると思いますが、式が複雑すぎて使用できないかどうかはわかりません。コードを関数に移動しようとしましたが、同じです。キーはこの決定論的なもの(間違っていますか?)および/または元の列に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 に答える