4 Oracle Textの索引の作成

Oracle Text索引を作成する方法を学習します。

この章のトピックは、次のとおりです:

4.1 Oracle Text索引の作成手順の概要

Oracle Textでは、CONTEXTCTXCATおよびCTXRULEタイプの索引を作成できます。

ASYNCHRONOUS_UPDATEパラメータ文字列オプションの使用によって古い索引エントリを維持して元の内容を検索することもできます。

デフォルトでは、システムはドキュメントがテキスト列に格納されるとみなします。この要件が満たされていると、プリファレンスを明示的に指定せずに、SQL文CREATE INDEXを使用して、Oracle Text索引を拡張可能な索引タイプCONTEXTとして作成できます。システムでは、言語、テキスト列のデータ型、およびドキュメントの形式が自動的に検出されます。次に、索引プリファレンスが設定されます。

Oracle Textの索引を作成するには:

  1. (オプション)デフォルトを使用しない場合は、カスタムの索引プリファレンス、セクション・グループまたはストップリストを指定します。次の表は、これらの索引クラスを説明しています。

    クラス 説明

    データストア

    ドキュメントの保存方法

    フィルタ

    ドキュメントのプレーン・テキストへの変換方法

    レクサー

    索引付け対象の言語

    ワードリスト

    ステミング問合せおよびファジー問合せの拡張方法

    記憶域

    索引データの格納方法

    ストップリスト

    索引付け対象外のワードまたはテーマ

    セクション・グループ

    ドキュメント・セクションの定義方法

  2. (オプション)カスタム・プリファレンス、セクション・グループまたはストップリストを作成します。

  3. CREATE INDEX SQL文を使用してOracle Text索引を作成します。索引に名前を付け、必要に応じてプリファレンスを指定します。

4.2 プリファレンスの作成

必要に応じて、カスタムの索引プリファレンスを作成してデフォルトをオーバーライドできます。ファイルの格納場所やドキュメントのフィルタ処理方法などの索引情報を指定するには、プリファレンスを使用します。プリファレンスを作成した後、属性を設定します。

4.3 セクション検索の例: HTMLセクションの作成

HTMLやXMLのように、ドキュメントに内部構造がある場合は、索引付け操作前に埋込みタグを使用してドキュメントのセクションを定義できます。このアプローチによって、WITHIN演算子を使用してセクション内で問合せができます。セクションは、セクション・グループの構成要素として定義します。

この例は、HTML_SECTION_GROUP型のhtmgroupというセクション・グループを定義します。次に、<H1>タグで識別されるheadingというゾーン・セクションをhtmgroup内に作成します。

begin
ctx_ddl.create_section_group('htmgroup', 'HTML_SECTION_GROUP');
ctx_ddl.add_zone_section('htmgroup', 'heading', 'H1');
end;

4.4 ストップワードおよびストップリストの使用

ストップワードとは、英語のthisthatなど、索引付け対象外の単語のことです。

システムでは各言語のストップリストが用意されています。デフォルトでは、索引付け時に使用言語に対して、Oracle Textのデフォルトのストップリストが使用されます。

デフォルトのCTXSYS.DEFAULT_STOPLISTを編集するか、次のPL/SQLプロシージャを使用して独自のリストを作成できます。

  • CTX_DDL.CREATE_STOPLIST

  • CTX_DDL.ADD_STOPWORD

  • CTX_DDL.REMOVE_STOPWORD

CREATE INDEXのPARAMETERS句に、カスタムのストップリストを指定します。

また、索引を作成した後で、ALTER INDEX文でストップワードを動的に追加することもできます。

4.4.1 マルチ言語のストップリスト

言語固有のストップワードを保持するマルチ言語のストップリストを作成できます。このストップリストは、英語、ドイツ語および日本語などの異なる言語のドキュメントを含む表を索引付けするためにMULTI_LEXERを使用している場合に有効です。

マルチ言語ストップリストを作成するには、CTX_DDL.CREATE_STOPLISTプロシージャを使用し、MULTI_STOPLISTというストップリスト・タイプを指定します。CTX_DDL.ADD_STOPWORDを使用して言語固有のストップワードを追加します。

4.4.2 ストップテーマとストップクラス

独自のストップワードの定義に加えて、ストップテーマ(索引付けされないテーマ)も定義できます。この機能が使用できるのは、英語およびフランス語のみです。

数値が索引付け対象外であることも指定できます。索引付け対象外の数値のような英数字のクラスは、ストップクラスと呼ばれます。

ストップワード、ストップテーマおよびストップクラスを追加する単一のストップリストを作成し、CREATE INDEXparamstringでそのストップリストを指定します。

4.4.3 ストップリスト管理のためのPL/SQLプロシージャ

次のプロシージャを使用してストップリスト、ストップワード、ストップテーマおよびストップクラスを管理します。

  • CTX_DDL.CREATE_STOPLIST

  • CTX_DDL.ADD_STOPWORD

  • CTX_DDL.ADD_STOPTHEME

  • CTX_DDL.ADD_STOPCLASS

  • CTX_DDL.REMOVE_STOPWORD

  • CTX_DDL.REMOVE_STOPTHEME

  • CTX_DDL.REMOVE_STOPCLASS

  • CTX_DDL.DROP_STOPLIST

    関連項目:

    これらのプロシージャの使用方法についてさらに学習するには、『Oracle Textリファレンス』を参照してください。

4.5 CONTEXT索引の作成

CONTEXT索引タイプは、Microsoft Word、HTMLまたはプレーン・テキストのような形式の大量のまとまったドキュメントを索引付けする場合に最適です。CONTEXT索引では、様々な方法で索引をカスタマイズすることもできます。ドキュメントはテキスト表にロードする必要があります。

この項には、次の項目が含まれます。

4.5.1 CONTEXT索引およびDML

CONTEXT索引は、トランザクション・ベースでは更新されません。レコードを削除すると、索引は即時に変更されます。つまり、変更を行った瞬間からセッションはレコードを検索しなくなり、コミット後には他のユーザーはレコードを検索できなくなります。挿入と更新の場合、索引の同期化が行われるまで、新しい情報はテキスト検索には表示されません。したがって、元表で挿入または更新を行う場合、CTX_DDL.SYNC_INDEX.を使用して明示的に索引を同期化する必要があります

関連項目:

索引の同期化

4.5.2 「デフォルトのCONTEXT索引例」

次の文は、docs表内のtext列にmyindexというデフォルトのCONTEXT索引を作成します。

CREATE INDEX myindex ON docs(text) INDEXTYPE IS CTXSYS.CONTEXT;

パラメータを明示的に指定せずにCREATE INDEX文を使用すると、すべての言語に対してシステムのデフォルト動作が次のようになります。

  • 索引付けされるテキストは、テキスト列に直接格納されるとみなします。テキスト列の型は、CLOBBLOBBFILEVARCHAR2またはCHARになります。

  • 列型を検出し、バイナリの列型(BLOBおよびBFILE)に対してフィルタ処理を使用します。ほとんどのドキュメント形式がフィルタ処理でサポートされています。列がプレーン・テキストの場合、システムはフィルタ処理を使用しません。

    ノート:

    システムで正しくドキュメントをフィルタ処理するために、使用している環境がAUTO_FILTERフィルタをサポートするように正しく設定されていることを確認してください。

  • 索引付けするテキストの言語は、データベース設定で指定された言語であるとみなします。

  • データベース設定で指定した言語に対するデフォルトのストップリストを使用します。ストップリストは、索引付け時にシステムが無視するワードを識別します。

  • 使用言語でのファジーおよびステミング問合せを有効にします(その言語に対してこの機能が使用可能な場合)。

デフォルトの索引付け動作は、プリファレンスをカスタマイズし、そのプリファレンスをCREATE INDEXのパラメータ文字列に指定することによって、いつでも変更できます。

関連項目:

AUTO_FILTERフィルタを使用するための環境の構成についてさらに学習するには、『Oracle Text リファレンス』を参照してください

4.5.3 ALTER INDEXおよびCREATE INDEXによる索引の追加的な作成

ALTER INDEX文およびCREATE INDEX文は、CONTEXTグローバル索引の追加的な作成をサポートします。

  • グローバル索引の場合、CREATE INDEXを使用してREBUILD句のREPLACEパラメータでNOPOPULATEキーワードをサポートします。これにより、索引を追加的に作成できます。このキーワードは、索引付け処理を連続的に実行するのが困難な大規模なインストールでOracle Text索引を作成する場合に便利です。

  • ローカル索引パーティションについて、ALTER INDEX ... REBUILD partition ... parameters ('REPLACE ...')パラメータ文字列を、NOPOPULATEキーワードをサポートするように修正します。

  • ローカル索引パーティションについては、CREATE INDEX ... LOCAL ... (partition ... parameters ('NOPOPULATE'))がサポートされています。パーティション・レベルのPOPULATEキーワードまたはNOPOPULATEキーワードは、索引レベルで指定されたPOPULATEまたはNOPOPULATEを上書きします。

関連項目:

ALTER INDEX文およびCREATE INDEX文の構文についてさらに学習するには、『Oracle Textリファレンス』を参照してください。

4.5.4 POPULATE_PENDINGによるCONTEXT索引の追加的な作成

索引付け処理を連続的に実行するのが困難な大規模なインストールの場合、CTX_DDL.POPULATE_PENDINGプロシージャを使用します。このプロシージャでは、索引の作成をより細かく制御することもできます。望ましい方法は、空の索引を作成して、すべてのROWIDを保留キューに配置し、CTX_DDL.SYNC_INDEX.を介して索引を構築する方法です

このプロシージャにより、元表および表パーティション内のすべてのROWIDが保留中のキューに移入されます。

関連項目:

CTX_DDL.POPULATE_PENDINGの詳細は、『Oracle Textリファレンス』を参照してください。

4.5.5 カスタムのCONTEXT索引例: HTMLドキュメントの索引付け

URLで指定されたHTMLドキュメント・セットを索引付けする場合は、CREATE INDEX文でシステム定義プリファレンスであるNULL_FILTERを指定します。

HTML_SECTION_GROUPを使用するhtmgroupセクション・グループおよびNETWORK_DATASTOREを使用するNETWORK_PREFデータストアを指定できます。

begin
 ctx_ddl.create_preference('NETWORK_PREF','NETWORK_DATASTORE');
 ctx_ddl.set_attribute('NETWORK_PREF','HTTP_PROXY','www-proxy.us.example.com');
 ctx_ddl.set_attribute('NETWORK_PREF','NO_PROXY','us.example.com');
 ctx_ddl.set_attribute('NETWORK_PREF','TIMEOUT','300');
end;

begin
ctx_ddl.create_section_group('htmgroup', 'HTML_SECTION_GROUP');
ctx_ddl.add_zone_section('htmgroup', 'heading', 'H1');
end;

それから、ドキュメントを索引付けできます。

CREATE INDEX myindex on docs(htmlfile) indextype is ctxsys.context 
parameters(
'datastore NETWORK_PREF filter ctxsys.null_filter section group htmgroup'
);

ノート:

Oracle Database 19c以降、Oracle TextのURL_DATASTORE型は非推奨になりました。かわりに、NETWORK_DATASTOREを使用してください。

4.5.6 CONTEXT索引例: FILTER BYおよびORDER BYによる問合せ処理

複合問合せで問合せ処理を効率化し応答時間を短縮するため、次の例に示すようにFILTER BY句およびORDER BY句を使用します。

CREATE INDEX myindex on docs(text) INDEXTYPE is CTXSYS.CONTEXT
FILTER BY category, publisher, pub_date
ORDER BY pub_date desc;

問合せ時にFILTER BY category, publisher, pub_date句を指定したため、Oracle Textではこれらの列上の関連の述語をOracle Text索引の行ソースに入れることも考慮します。

また、問合せに一致するORDER BY条件がある場合、応答時間を短縮するために、ORDER BY pub_date descを指定することで、Oracle Textにより、SORTをOracle Text索引の行ソースに入れるかどうかが決定されます。

4.5.7 リリース12cのDATASTOREトリガー

複数の列にOracle TextのCONTEXT索引を作成する場合は、索引付けのための様々な列を得るためにMULTI_COLUMN_DATASTOREまたはUSER_DATASTOREを使用します。Oracle Textでは、指定された列の内容が変更された場合にのみ索引が更新されます。

4.6 CTXCAT索引の作成

CTXCAT索引タイプは、小さなテキスト断片や関連情報の索引付けに最適です。この索引タイプは、CONTEXT索引よりも優れた構造化問合せのパフォーマンスが得られます。

4.6.1 CTXCAT索引とDML操作

CTXCAT索引は、トランザクション・ベースで更新されます。元表で挿入、更新および削除を実行すると、索引が自動的に同期化されます。CONTEXT索引と異なり、CTX_DDL.SYNC_INDEXは不要です。

ノート:

トリガーを起動せずに挿入を実行するアプリケーション(SQL*Loaderなど)では、前述の索引の自動同期化は行われません。

4.6.2 CTXCATサブ索引とそのコスト

CTXCAT索引には、索引セットの構成要素として定義したサブ索引が含まれます。1つ以上の列にサブ索引を作成すると、複合問合せのパフォーマンスが向上します。ただし、CTXCAT索引の作成に要する時間は、その総サイズによって異なります。CTXCAT索引の総サイズに直接関係する要因は、次のとおりです。

  • 索引付けするテキストの合計数

  • 索引セットに含まれるサブ索引の数

  • サブ索引を構成する元表の列数

索引セットにコンポーネント索引が多数ある場合も、更新する必要がある索引が多くなるため、挿入、更新および削除操作のパフォーマンスが低下します。

CTXCAT索引の作成には追加の索引付け時間とディスク領域が必要になるため、索引セットにコンポーネント索引を追加する前に、それぞれのコンポーネント索引によってアプリケーションに提供される問合せパフォーマンス上のメリットを慎重に考慮する必要があります。

ノート:

BASIC_STORAGEI_ROWID_INDEX_CLAUSEを使用すると、CTXCAT索引の作成を高速化できます。この句については、『Oracle Textリファレンス』で説明しています。

4.6.3 CTXCATサブ索引の作成

オンライン・オークション・サイトでは、品目の説明、価格、入札終了日などの情報を格納し、参照する必要があるため、CTXCAT索引作成のよい例です。

図4-1 Auction表のスキーマとCTXCAT索引

図4-1の説明が続きます
「図4-1 Auction表のスキーマとCTXCAT索引」の説明

図4-1は、次のスキーマを使用したAUCTIONという表を示しています。

create table auction(
item_id number,
title varchar2(100),
category_id number,
price number,
bid_close date);

サブ索引を作成するには、サブ索引を格納する索引セットを作成します。

begin
ctx_ddl.create_index_set('auction_iset');
end;

次に、入力する可能性がある構造化問合せを特定します。CATSEARCH問合せ演算子では、必須のテキスト句とオプションの構造化句を使用します。

この例では、すべての問合せにテキスト列であるtitle列の句が組み込まれています。

構造化句は、次のカテゴリに分類されるとします。

構造化句 問合せを満たすサブ索引の定義 カテゴリ

'price < 200'

'price = 150'

'order by price'

'price'

A

'price = 100 order by bid_close'

'order by price, bid_close'

'price, bid_close'

B

構造化問合せ句カテゴリA

構造化問合せ句には、次のように、price列のみの式が含まれています。

SELECT FROM auction WHERE CATSEARCH(title, 'camera', 'price < 200')> 0;
SELECT FROM auction WHERE CATSEARCH(title, 'camera', 'price = 150')> 0;
SELECT FROM auction WHERE CATSEARCH(title, 'camera', 'order by price')> 0;

これらの問合せはサブ索引Bを使用して処理できます。ただし、効率を考えてpriceにのみ索引(サブ索引A)を作成することもできます。

begin
ctx_ddl.add_index('auction_iset','price'); /* sub-index A */
end;

構造化問合せ句カテゴリB

構造化問合せ句には、priceについての等式にbid_closeでのソートの条件が付与されたもの、およびpricebid_closeの両方で(この順に)ソートの条件が付与されたものが含まれます。

SELECT FROM auction WHERE CATSEARCH(
   title, 'camera','price = 100 
   ORDER BY bid_close')> 0;
SELECT FROM auction 
   WHERE CATSEARCH(
   title, 'camera','order by price, bid_close')> 0;

これらの問合せは、次のように定義したサブ索引で満たすことができます。

begin
ctx_ddl.add_index('auction_iset','price, bid_close'); /* sub-index B */
end;

結合されたBツリー索引と同様に、CTX_DDL.ADD_INDEXを使用して指定する列の順序は、特定の問合せを満たすために使用される索引スキャンの効率性および実行可能性に影響します。たとえば、2つの構造化列pqにBツリー索引が'p,q'として指定されている場合、Oracle Textでは、この索引をスキャンして'ORDER BY q,p'をソートできません。

4.6.4 CTXCAT索引の作成

この例では、前述の例を結合し、2つのサブ索引を持つ索引セット・プリファレンスを作成します。

begin
ctx_ddl.create_index_set('auction_iset');
ctx_ddl.add_index('auction_iset','price'); /* sub-index A */
ctx_ddl.add_index('auction_iset','price, bid_close'); /* sub-index B */
end;

図4-1は、サブ索引AおよびBをAUCTION表から作成する方法を示しています。各サブ索引はそれぞれテキスト列と名前付き構造化列のBツリー索引です。たとえば、サブ索引Aは、title列とbid_close列の索引です。

結合されたカタログ索引は、CREATE INDEX文を使用して次のように作成します。

CREATE INDEX auction_titlex ON AUCTION(title) 
  INDEXTYPE IS CTXSYS.CTXCAT 
  PARAMETERS ('index set auction_iset')
;

関連項目:

CREATEINDEXを使用したCTXCAT索引の作成方法についてさらに学習するには、『Oracle Textリファレンス』を参照してください。

4.7 CTXRULE索引の作成

ドキュメント分類アプリケーションを作成するには、表または問合せにCTXRULE索引を使用します。着信ドキュメントのストリームがコンテンツで分類されると、問合せによりカテゴリが定義されます。単一ドキュメントの分類には、MATCHES演算子を使用できます。

CTXRULE索引および単純なドキュメント分類アプリケーションを作成するには、次の手順に従います。

  1. 問合せの表を作成します。

    カテゴリ名および問合せテキストを保持するmyqueries表を作成し、この表に分類と各分類を定義する問合せを移入します。

    CREATE TABLE myqueries (
    queryid NUMBER PRIMARY KEY,
    category VARCHAR2(30),
    query VARCHAR2(2000)
    );
    

    たとえば、主題US PoliticsMusicおよびSoccerの分類を考えてみます。

    INSERT INTO myqueries VALUES(1, 'US Politics', 'democrat or republican');
    INSERT INTO myqueries VALUES(2, 'Music', 'ABOUT(music)');
    INSERT INTO myqueries VALUES(3, 'Soccer', 'ABOUT(soccer)');

    ヒント:

    ルール(または問合せ)の表の生成には、CTX_CLS.TRAINプロシージャも使用できます。このプロシージャは入力としてドキュメント・トレーニング・セットを取ります。

  2. CTXRULE索引を作成します。

    CREATE INDEX文を使用してCTXRULE索引を作成し、必要に応じてレクサー、記憶域、セクション・グループおよびワードリストの各パラメータを指定します。

    CREATE INDEX myruleindex ON myqueries(query)
         INDEXTYPE IS CTXRULE PARAMETERS
               ('lexer lexer_pref 
                 storage storage_pref 
                 section group section_pref 
                 wordlist wordlist_pref');
  3. ドキュメントを分類します。

    MATCHES演算子を使用してドキュメントを分類します。

    着信ドキュメントは表newsに格納されるとします。

    CREATE TABLE news ( 
    newsid NUMBER,
    author VARCHAR2(30),
    source VARCHAR2(30),
    article CLOB);
    

    必要に応じて、MATCHESで「BEFORE INSERT」トリガーを作成して、各ドキュメントをそれぞれの分類に基づいて別の表news_routeにルーティングします。

    BEGIN
      -- find matching queries
      FOR c1 IN (select category
                   from myqueries
                  where MATCHES(query, :new.article)>0) 
      LOOP
        INSERT INTO news_route(newsid, category)
          VALUES (:new.newsid, c1.category);
      END LOOP;
    END;

関連項目:

4.8 JSONの検索索引の作成

Oracle Textは、JavaScriptオブジェクト注釈(JSON)で検索索引を作成するための簡易な代替構文をサポートします。JSON検索索引は表の列名に作成されます。