13

Oracle Text CTXSYS.CONTEXT 索引を使用して、メタ情報を含む約50万行の索引を作成しています。情報は、実行時にインデクサーが呼び出すプロシージャによって結合される 2 つのテーブルに分散されます (関数インデックス)。

ローカル マシン (単純なデュアルコア ノートブック) で CREATE INDEX を実行すると、約 3 分でインデックスが作成されます。8 コアと 16G の RAM を搭載した Solaris 上で動作する DB サーバーでは、同じ (まったく同じ) データのインデックスを作成するのに約 24 時間かかります。

サンプル コード: これは、2 つのテーブルと 3 つの列のインデックス フィーダーです。

create or replace procedure docmeta_revisions_text_feeder 
    ( p_rowid in rowid , p_clob in out nocopy clob) as v_clob CLOB begin
    FOR c1 IN (select DM.DID, DM.XDESCRIB || ' ' || DM.XAUTHOR AS data
        from DOCMETA DM
        WHERE ROWID = p_rowid) 
    LOOP
        v_clob := v_clob || c1.data;
        FOR c2 IN (
            SELECT ' ' || RV.DDOCTITLE AS data
            FROM   REVISIONS RV
            WHERE  RV.DID = c1.DID)
        LOOP
            v_clob := v_clob || c2.data;
        END LOOP;
    END LOOP;
    p_clob := v_clob;    
    end docmeta_revisions_text_feeder

これらは好みです

BEGIN
CTX_DDL.CREATE_PREFERENCE ('concat_DM_RV_DS', 'USER_DATASTORE');
CTX_DDL.SET_ATTRIBUTE ('concat_DM_RV_DS', 'PROCEDURE',
'docmeta_revisions_text_feeder');
 END;

次に、インデックスを作成します

CREATE INDEX concat_DM_RV_idx ON DOCMETA (FULLTEXTIDX_DUMMY)
INDEXTYPE IS CTXSYS.CONTEXT
PARAMETERS ('datastore concat_DM_RV_DS 
section group CTXSYS.AUTO_SECTION_GROUP
') PARALLEL 4;

データの大部分は、簡単なタイトルまたは著者名 + 1k 未満のテキストによる短い説明で構成されます。

関連するメモリ設定と PARALLEL パラメータを少し試してみましたが、成功しませんでした。だからここに私の質問があります:

  • インデックス作成プロセスを一時停止して再開する方法はありますか (私は CTX_SYS ロールを手元に持っています)。
  • どのパラメータを微調整できるか(特にメモリサイズ)のヒントはありますか?
  • テキスト索引をエクスポートおよびインポートできますか? -> 次に、ローカル マシンでインデックス作成を実行し、それをサーバーにコピーするだけです。
  • インデクサーは「低い優先度」で実行できますか?
  • ロック操作によってインデクサーが乱れた可能性があります (他のユーザーが並行してアクセスするステージング マシンです)。関連するテーブルをロックし、インデックスを作成して後でロックを解除する方法はありますか?
4

1 に答える 1

12

最終的に、インデックスの分割同期を行う方法を見つけました。以下は、私たちが行ったことを示すいくつかの基本的な手順です。

CREATE INDEX concat_DM_RV_idx ON DOCMETA (FULLTEXTIDX_DUMMY)
INDEXTYPE IS CTXSYS.CONTEXT
PARAMETERS ('datastore concat_DM_RV_DS section group CTXSYS.AUTO_SECTION_GROUP
NOPOPULATE
');

NOPOPULATE パラメータを参照してください。これは、インデクサーに、データの取り込み/インデックス作成プロセスを開始すべきではないことを伝えます。11g を使用している場合は、インデックスを自由に設定する非常に優れた CTX_DDL 機能、つまりプロシージャ "POPULATE_PENDING" をすぐに利用できます。インデックス名で呼び出すと、変更されたために同期されていない行を保持する CTXSYS テーブルにデータが入力されます。このメソッドを呼び出した後、インデクサーはまだ何も開始していないことに注意してください。10g (?) 以降、対応する CTX_DDL.SYNC_INDEX プロシージャには、「maxtime」パラメータなど、いくつかの追加パラメータがあります。たとえば、4H を指定すると、インデクサーは保留中の行の同期を約 4 時間開始します。スケジュールに従ってその手順を繰り返して完了です。

残念ながら 9i では動作しません。そこで、Oracle の POPULATE_PENDING プロセスを「シミュレート」することに成功しました。このメソッドの唯一の制限は、テーブルから同じコンテンツのチャンクをクエリできるようにするために、ある種の一意の行識別子が必要であることです。行ったことは次のとおりです。

1.) NOPOPULATE を使用してインデックスを作成します (上記を参照)。 2.) SYS / DBA / CTXSYS になります (管理者に連絡してください)。インデックス メタ テーブルをクエリして、新しく作成したインデックスの ID を確認します。

SELECT IDX_ID FROM CTXSYS.CTX_INDEXES WHERE IDX_NAME ='concat_DM_RV_idx';

3.) これが生成するインデックス ID を紙の黄色いスニペットに書き留め、この挿入ステートメントを CTXSYS ロールとして実行し、<> をインデックス ID に置き換え、<> をインデックスが構築されているテーブルの名前に置き換えます。一意の行識別子は、ある種のドキュメント ID またはテーブルのデータの一意のチャンクを作成する任意の種類のカウント可能なステートメントにすることができます。

INSERT INTO CTXSYS.DR$PENDING (PND_CID,PND_PID,PND_ROWID,PND_TIMESTAMP)
SELECT <<your index id>>, 0, <<basetable name>>.ROWID, CURRENT_DATE
FROM gsms.DOCMETA
WHERE <<basetable unique row identifier>> < 50000;
COMMIT; -- Dont forget the COMMIT! DONT FORGET IT!!! WE MEAN IT!

「50.000」は、インデクサーのペイロードとして保留中の行テーブルに挿入されるベーステーブルの不足に応じて、行数をマークします。必要に応じて調整してください。

4.) これで、インデクサーを緩める準備が整いました。

CALL CTX_DDL.SYNC_INDEX(
  'CONCAT_DM_RV_IDX', -- your index name here
  '100M', -- memory count
  NULL, -- param for partitioned idxes
  2 -- parallel count
);

ステップ 3 で挿入した行数に関係なく、インデックス作成プロセスが開始されます。) 次のチャンクを実行するには、ステップ 3 を繰り返します。

同じ行セットに対して誤ってインデクサーを実行すると、インデックスが大幅に断片化されます。これをクリーンアップする唯一の方法は、REBUILD パラメータを使用してインデックスを最適化することです。インデクサーを実行する必要がなく、インデックス テーブルの内容を再配置するだけなので、ローカル マシンは非常に高速でした。

CALL CTX_DDL.OPTIMIZE_INDEX('CONCAT_DM_RV_IDX', 'REBUILD');

インデックス作成のステータスとサイズに関するメタ情報が必要な場合は、CTX_REPORT パッケージに問い合わせることができます。

SELECT CTX_REPORT.INDEX_SIZE('CONCAT_DM_RV_IDX') FROM DUAL;

また、インデックス作成時に選択したパラメータを忘れた場合:

SELECT * FROM CTXSYS.CTX_PARAMETERS;

インデックス作成をお楽しみください。

于 2010-07-28T07:51:54.117 に答える