3

Oracle 11.2.0.1.0 のドメイン インデックスの開発中に (問題は 12с にも表示されます)、indextype WITH ARRAY DMLオプションを作成する場合、 関数ODCIIndexInsertのパラメーター タイプの誤解に直面しました。

Oracleのドキュメントhttp://docs.oracle.com/cd/E11882_01/appdev.112/e10765/ext_idx_ref.htm#i76892によると

WITH ARRAY DML オプションの場合、Oracle は次のシグネチャで ODCIIndexInsert を呼び出します。

FUNCTION ODCIIndexInsert(
  ia ODCIIndexInfo,
  ridlist ODCIRidList,
  newvallist varray_of_column_type,
  env ODCIEnv)
RETURN NUMBER

私の場合、インデックス付きの列のデータ型は NUMBER なので、varray_of_column_type を SYS.ODCINumberList として定義まし

STATIC FUNCTION ODCIIndexInsert(ia in sys.ODCIIndexInfo, ridlist in sys.ODCIRidList,  newvallist in sys.ODCINumberList, env in SYS.ODCIEnv) RETURN NUMBER

インデックスタイプは次のように作成されました

CREATE INDEXTYPE test_index_type
FOR
test_eq(number, number)
USING index_methods
WITH ARRAY DML(number, sys.ODCINumberList)
WITH LOCAL RANGE PARTITION
WITH SYSTEM MANAGED STORAGE TABLES;

また

CREATE INDEXTYPE test_index_type
FOR
test_eq(number, number)
USING index_methods
WITH ARRAY DML
WITH LOCAL RANGE PARTITION
WITH SYSTEM MANAGED STORAGE TABLES;

(すべての場合に問題が発生します)

CREATE TABLE test_table (id NUMBER (19,0));
CREATE INDEX test_index ON test_table(id) INDEXTYPE IS test_index_type;

テーブルにデータを挿入しようとしたとき

insert into test_table values (1);

オラクルは例外を発生させます

Error starting at line 53 in command:
insert into test_table values (1)
Error at Command Line:53 Column:1
Error report:
SQL Error: ORA-29925: cannot execute SCOTT.INDEX_METHODS.ODCIINDEXINSERT
ORA-06553: PLS-306: wrong number or types of arguments in call to 'ODCIINDEXINSERT'
ORA-06553: PLS-306: wrong number or types of arguments in call to 'ODCIINDEXINSERT'
29925. 00000 -  "cannot execute %s"
*Cause:    The specified function does not exist or does not have an
           appropriate signature.
*Action:   Implement the function with the appropriate signature.

だから私の質問はです。オラクルの通常の動作ですか(ドキュメントによると)?「WITH ARRAY DML」オプションを使用してINDEXTYPEを作成し、索引付けされた列のデータ型がNUMBERである場合のODCIIndexInsert関数の正しい署名は何ですか?

ちなみに、 「WITH ARRAY DML」オプションの署名なしでインデックスタイプを定義すると、明確で機能します。しかし、このアプローチはパフォーマンスのニーズを満たしていません。

また、オプション「WITH ARRAY DML WITHOUT COLUMN DATA」でインデックスタイプを定義し、署名を使用する場合

static function ODCIIndexInsert(ia sys.odciindexinfo,   ridlist sys.odciridlist, env sys.ODCIEnv) return number

すべても機能します。しかし、このアプローチは私たちのビジネス ニーズを満たしません。

ドキュメントに従ってバッチ挿入が機能するように、ODCIIndexInsertパラメータ型(インデックス番号列の場合)を定義する方法はありますか?

FUNCTION ODCIIndexInsert(
      ia ODCIIndexInfo,
      ridlist ODCIRidList,
      newvallist varray_of_column_type,
      env ODCIEnv)

環境を再作成して問題を再現するために、完全なSQLスクリプトを添付しています。

タイプ定義:

CREATE OR REPLACE TYPE index_methods AS OBJECT
(
  step number,
  STATIC FUNCTION ODCIGetInterfaces(ifclist OUT SYS.ODCIObjectList) RETURN NUMBER,
  STATIC FUNCTION ODCIIndexCreate (ia SYS.ODCIIndexInfo, parms VARCHAR2, env SYS.ODCIEnv) RETURN NUMBER,
  STATIC FUNCTION ODCIIndexAlter (ia sys.ODCIIndexInfo, parms IN OUT VARCHAR2, altopt number, env sys.ODCIEnv) RETURN NUMBER,
  STATIC FUNCTION ODCIIndexDrop(ia SYS.ODCIIndexInfo, env SYS.ODCIEnv) RETURN NUMBER,
  STATIC FUNCTION ODCIIndexExchangePartition(ia SYS.ODCIIndexInfo, ia1 SYS.ODCIIndexInfo, env SYS.ODCIEnv) RETURN NUMBER,
  STATIC FUNCTION ODCIIndexUpdPartMetadata(ia sys.ODCIIndexInfo, palist sys.ODCIPartInfoList, env sys.ODCIEnv) RETURN NUMBER,
  STATIC FUNCTION ODCIIndexInsert(ia in sys.ODCIIndexInfo, ridlist in sys.ODCIRidList,  newvallist in sys.ODCINumberList, env in SYS.ODCIEnv) RETURN NUMBER,
  STATIC FUNCTION ODCIIndexDelete(ia SYS.ODCIIndexInfo, rid VARCHAR2, oldval number, env SYS.ODCIEnv) RETURN NUMBER,
  STATIC FUNCTION ODCIIndexUpdate(ia SYS.ODCIIndexInfo, rid VARCHAR2, oldval number, newval number, env SYS.ODCIEnv) RETURN NUMBER,
  STATIC FUNCTION ODCIIndexStart(sctx IN OUT index_methods, ia SYS.ODCIIndexInfo,
    op SYS.ODCIPredInfo, qi sys.ODCIQueryInfo, strt number, stop number, cmpval number, env SYS.ODCIEnv) RETURN NUMBER,
  MEMBER FUNCTION ODCIIndexFetch(self IN OUT index_methods, nrows NUMBER, rids OUT SYS.ODCIridlist, env SYS.ODCIEnv) RETURN NUMBER,
  MEMBER FUNCTION ODCIIndexClose(self IN index_methods, env SYS.ODCIEnv) RETURN NUMBER
);

CREATE OR REPLACE TYPE BODY index_methods IS

STATIC FUNCTION ODCIGetInterfaces(ifclist OUT sys.ODCIObjectList) RETURN NUMBER IS
BEGIN
  ifclist := sys.ODCIObjectList(sys.ODCIObject('SYS','ODCIINDEX2'));
  RETURN ODCIConst.Success;
END ODCIGetInterfaces;

STATIC FUNCTION ODCIIndexCreate (ia sys.ODCIIndexInfo, parms VARCHAR2,  env sys.ODCIEnv) RETURN NUMBER IS
BEGIN
  RETURN ODCIConst.Success;
END ODCIIndexCreate;

STATIC FUNCTION ODCIIndexDrop(ia sys.ODCIIndexInfo, env sys.ODCIEnv) RETURN NUMBER IS
BEGIN
  RETURN ODCIConst.Success;
END ODCIIndexDrop;

STATIC FUNCTION ODCIIndexAlter (
  ia sys.ODCIIndexInfo,
  parms IN OUT VARCHAR2,
  altopt NUMBER,
  env sys.ODCIEnv)
RETURN NUMBER IS
BEGIN
  RETURN ODCIConst.Success;
END ODCIIndexAlter;

STATIC FUNCTION ODCIIndexUpdPartMetadata(
  ia sys.ODCIIndexInfo,
  palist sys.ODCIPartInfoList,
  env sys.ODCIEnv)
RETURN NUMBER IS
BEGIN
  RETURN ODCIConst.Success;
END ODCIIndexUpdPartMetadata;


STATIC FUNCTION ODCIIndexExchangePartition(
  ia sys.ODCIIndexInfo,
  ia1 sys.ODCIIndexInfo,
  env sys.ODCIEnv)
RETURN NUMBER IS 
BEGIN
  RETURN ODCIConst.Success;
END ODCIIndexExchangePartition;



STATIC FUNCTION ODCIIndexInsert(
   ia sys.ODCIIndexInfo,
   ridlist sys.ODCIRidList,
   newvallist sys.ODCINumberList,
   env sys.ODCIEnv)
RETURN NUMBER IS
BEGIN 
  return ODCIConst.Success;
END;

STATIC FUNCTION ODCIIndexDelete(
   ia SYS.ODCIIndexInfo,
   rid VARCHAR2,
   oldval number,
   env SYS.ODCIEnv)
RETURN NUMBER IS
BEGIN
  return ODCIConst.Success;
END;


STATIC FUNCTION ODCIIndexUpdate(
   ia SYS.ODCIIndexInfo,
   rid VARCHAR2,
   oldval number,
   newval number,
   env SYS.ODCIEnv)
RETURN NUMBER AS
BEGIN
  return ODCIConst.Success;
END;


STATIC FUNCTION ODCIIndexStart(
  sctx IN OUT index_methods,
  ia SYS.ODCIIndexInfo,
  op SYS.ODCIPredInfo,
  qi sys.ODCIQueryInfo,
  strt number,
  stop number,
  cmpval  number,
  env SYS.ODCIEnv)
RETURN NUMBER AS 
BEGIN
  sctx := index_methods(1);
  return ODCIConst.Success;
END;


MEMBER FUNCTION ODCIIndexFetch(
  self IN OUT index_methods,
  nrows NUMBER,
  rids OUT SYS.ODCIridlist,
  env SYS.ODCIEnv)
RETURN NUMBER AS
BEGIN
  return ODCIConst.Success;
END;


MEMBER FUNCTION ODCIIndexClose(self IN index_methods, env SYS.ODCIEnv) RETURN NUMBER AS
BEGIN
  return ODCIConst.Success;
END;

end;

問題の回避策:

--drop function test_eq_fun;

CREATE FUNCTION test_eq_fun(a number, b number) RETURN NUMBER AS
BEGIN
  IF a = b then
    RETURN 1;
  ELSE
    RETURN 0;
  END IF;
END;

--drop operator test_eq;
CREATE OPERATOR test_eq
BINDING (number, number) RETURN NUMBER
USING test_eq_fun;


--drop indextype test_index_type;
CREATE INDEXTYPE test_index_type
FOR
test_eq(number, number)
USING index_methods
WITH ARRAY DML(number, sys.ODCINumberList)
WITH LOCAL RANGE PARTITION
WITH SYSTEM MANAGED STORAGE TABLES;

/*
CREATE INDEXTYPE test_index_type
FOR
test_eq(number, number)
USING index_methods
WITH ARRAY DML
WITH LOCAL RANGE PARTITION
WITH SYSTEM MANAGED STORAGE TABLES;
*/


--drop table test_table;
CREATE TABLE test_table (id NUMBER (19,0));

CREATE INDEX test_index ON test_table(id) INDEXTYPE IS test_index_type;


insert into test_table values (1);
4

2 に答える 2

1

https://forums.oracle.com/thread/2582903で正しい回答が得られた ので、調査をクロスポストしてナレッジベースを埋めました。

「WITH ARRAY DML」オプションを使用する場合。単一行バージョンの挿入メソッドと複数行バージョンの挿入メソッドの両方を実装する必要があります。

単一行を挿入すると、Oracle は常にメソッドの単一行バージョンを呼び出します。

ただし、複数の行を1つに挿入すると、オラクルは単一行と複数行の方法で組み合わせを呼び出します。

テーブルがパーティション化されていない場合、2 つ以上のレコードを挿入すると、オラクルは複数行バージョンを呼び出します。

表がパーティション化されている場合、データが挿入されるセクションごとにODCIIndexInsertが起動されます。したがって、5 つのパーティションに 5 つの行を挿入すると (1 つのパーティションに 1 つの行)、Oracle は単一のメソッドを 5 回呼び出します。ただし、パーティション oracle に 2 つ以上の行を挿入する場合、そのパーティションに対して複数行バージョンのメソッドが呼び出されます。

これが役立つことを願っています。

于 2013-09-18T09:03:02.387 に答える
0

また、1) WITH ARRAY DML オプションを使用しても、Oracle が ODCIIndexInsert への 1 回の呼び出しですべての行を INSERT することは保証されないことにも注意してください。Oracle が ODCIIndexInsert の ARRAY DML バージョンを複数回呼び出して、すべての行を挿入する例を見てきました。私の例では、Oracle は毎回 200 行から 53 行の間で常に nrows を変更していました。これは、SGA メモリ サイズ、バッファ設定、および挿入する行のサイズに依存すると思います。これを回避する方法をご存知でしたら教えていただきたいです

2) ODCIIndexDelete には、同様の WITH ARRAY DML オプションがありません。一度に 1 行ずつ実行する必要があるため、DELETE の速度が大幅に低下します。面白いことに、Oracle Text カートリッジ オブジェクト TextIndexMethods には、配列 dml (ridlist ODCINUMBERLIST) のインタフェースで定義された ODCIIndexDelete があります。

于 2013-09-23T15:10:28.837 に答える