Oracle Text について

*以下は、サポート契約締結中のお客様に毎月配信しているサポートレターより一部抜粋して掲載しています。

Oracle Text とは?

皆様は「全文検索」をご存知ですか。マニュアル、報告書、Mail、WEB ページなどの文書から特定の文字列を検索することを全文検索と呼びます。

「全文検索」は、Web の検索エンジンサイトを考えると、イメージし易いかと思います。
Yahoo! や Google といった検索エンジンサイトを利用し、文字列を検索すると、その文字列を含む該当ページが表示されます。これは、Web 上の様々な情報ソースに対して、文字列による「全文検索」を、実行した結果から表示されているのです。

Oracle Text は Oracle が提供している全文検索機能です。Oracle Text では検索対象の文書全文に対し予め特別な索引付けを行います。文書を短い文字列(トークン)に分解し、出現位置の情報(どの文書のどの位置にトークンが出現するか)を付けてテキスト索引に格納するという動作になります。

※ 例えば、"I want to eat sushi."という内容の文書に対して、テキスト索引付けると、以下のような情報をテキスト索引に格納されます。

   ---------
   I     1-1
   want  1-2
   to    1-3
   eat   1-4
   sushi 1-5
   ---------

検索時には、検索文字列も同じ仕組み(レクサー)でトークンに分解し、索引に格納した当該トークンの出現位置情報を利用して、検索対象文書をひとつひとつ検索する(例えば、LIKE 検索)より高速な全文検索が実現できます。

また、Oracle Text では、様々な書式(HTML、XML、PDF、MS Office など)が設定されたドキュメントを対応するには、フィルタを使ってテキスト情報を抽出し、それに対して索引付けします。文書ファイルを Oracle データベースに格納する必要はありません。

次のようなご要望・課題をお持ちのお客様に最適!

  • 通常業務の中、非構造化データを扱うことが多い
    ※ 日常会話をそのままテキスト化した文章データ(例えば、Web ページやマニュアルなど)のような構造を持たないデータ
  • 高速な全文検索を実現したい
  • 検索時のヒット率を向上したい

Oracle Text の使用条件は?

利用可能なバージョン

Oracle8i Database Release 8.1.6 以降で利用可能です。

利用可能なエディション

Oracle Database の全てのエディションで利用可能です。つまり、全てのエディションにおいて、標準でご使用いただくことが可能です。

インストールが必要か?

Database Configuration Assistant(DBCA)を使用してデータベースを作成した場合、Oracle Text はデフォルトでインストールされます。

Oracle Text が使用可能かどうかの確認

SYS ユーザでデータベースにログインし、「CTXSYS」というユーザが存在するかどうか確認してください。

  $ sqlplus / as sysdba
  SQL> select username from dba_users
       where username='CTXSYS';

実行結果例)

   USERNAME
   ---------
   CTXSYS

CTXSYS ユーザが存在していない場合、Oracle Text がインストールされていない環境です。

インストール

Oracle Text がインストールされていない場合、DBCA を使用して Oracle Text コンポーネントをインストールすることが可能です。

実際に使ってみよう!

ユーザに権限付与からテキスト検索ができるようになるまでの一連の流れを簡単にご紹介いたします。

1. 権限の付与

Oracle Text索引を作成する、または Oracle Text PL/SQL パッケージ(CTX_DDLなど)を使用するには、CTXAPP ロールを持つ必要があります。

SQL> connect ctxsys/<パスワード>
SQL> grant ctxapp to scott;

※ CTXSYS ユーザがロックされていることがありますので、まず以下の SQL 文で CTXSYSがロックしているかどうかを確認してください。

     $ sqlplus / as sysdba
     SQL> select username,account_status from dba_users where username='CTXSYS';

実行結果例)

     USERNAME   ACCOUNT_STATUS
     ---------- ---------------
     CTXSYS     EXPIRED & LOCKED

上記の例のように CTXSYS がロックしている場合、以下の手順で CTXSYS をアンロックしてください。

SQL> alter user ctxsys identified by <パスワード> account unlock;

2. テスト用の表と索引の作成

テスト用の表の作成

  SQL> create table TEST (ID varchar2(2),
                          TEXT varchar2(20),
                          IDX_TEXT varchar2(20));

プリファレンスの作成

  SQL> exec ctx_ddl.create_preference('t_lexer_pref','JAPANESE_LEXER');

※ Text 索引の属性(例えば、どのレクサー使用か)の設定をするのがプリファレンスです。JAPANESE_LEXER は日本語を扱うレクサーになります。

Text 索引の作成

  SQL> create index TEST_IDX on TEST(IDX_TEXT)
       indextype is ctxsys.context
       parameters('LEXER t_lexer_pref SYNC(MANUAL)');

表にデータを挿入

  SQL> insert into TEST values ( 1 , 'オラクル','オラクル');
  SQL> insert into TEST values ( 2, 'オラ クル', 'オラクル');
  SQL> commit;

3. Text 索引の同期化

Text 索引の同期化については、詳しく後述いたします。

  SQL> exec ctx_ddl.sync_index('TEST_IDX'); 
  SQL> select * from CTX_USER_INDEX_ERRORS;

4. LIKE 検索と比較

  SQL> select ID,IDX_TEXT from TEST where CONTAINS (IDX_TEXT, 'オラクル') >0;
       ID     TEXT_VCHAR
       ------ --------------
       1      オラクル
       2      オラ クル
   
  SQL> select ID,TEXT from TEST where TEXT like '%オラクル%';

レコードが選択されませんでした。

一部の単語(語句)を条件に、テキスト文書の中ヒットから曖昧検索を行うことの点から、LIKE 検索と Text 索引を使用した検索と似ていますので、ここで両方を比較してみました。

Like では全角・半角、大文字・小文字の区別、空白等も考慮しますので、上記の例では「オラクル」を条件で指定すると、1件もヒットしません。JAPANESE_LEXER では、全角半角の区別がなく、空白も考慮されませんので、「オラクル」を条件で指定する時、2件がヒットし、Like 検索よりヒット率が高くなります。

索引の同期化に注意!

Text 索引について検索対象の表に対する DML 処理後、その処理内容を索引情報に反映させる※ 必要があります。
※ これは同期化(SYNC)と呼ばれます。テキストへの索引付けを行います。

同期化を行わないと、表に対するデータの更新(DML 処理)が Text 索引に反映されませんので、索引を使って検索すると、検索結果が古いままの情報となります。

SYSAUX が肥大化する

DML 処理が行われた後、同期化が行われるまでの間の保留状態となっている DML に関する情報が、Oracle Text の管理用のユーザ CTXSYS の表 DR$PENDING や DR$WAITINGに格納されます。
Text 索引が同期化されると DR$PENDING や DR$WAITING からデータ削除が行われます。
Text索引を作成している表の列に対して DMLを発行しているが、Text索引の同期化処理が行われていない場合、 セグメント DR$PENDING や DR$WAITING のサイズが増加し続けます。

その場合、スキーマ CTXSYS の表を格納している表領域 SYSAUX が肥大化することがあります。
従って、Text 索引を作成している場合、定期的に ctx_ddl.sync_index を使用して手動で同期化するか、自動同期化を行うように設定かをご検討ください。

「実際に使ってみよう!」の例やデフォルトでは、Text 索引の同期化方法を手動に設定しております。
索引を作成する時に SYNC を ON COMMIT もしくは EVERY "interval-string" に指定すると、索引の同期化がコミットの直後、もしくは時間ごとに自動的に実行されます。

例)コミットの直後に索引を同期化する

     SQL>create index TEST_IDX on TEST(IDX_TEXT)
         indextype is ctxsys.context
         parameters('SYNC(ON COMMIT)');

1時間ごとに索引を自動的に同期化する

     SQL>create index TEST_IDX on TEST(IDX_TEXT)
         indextype is ctxsys.context
         PARAMETERS ('SYNC(EVERY "sysdate+(1/24)")');

同期化中エラーが発生すると

Text 索引の同期化処理は、索引付け対象のテキストに無効な文字が含まれているなどの場合に、行に索引付けができず、エラーとなることがあります。

このようなエラーが発生した場合、同期化処理を実行したフロントにはエラーを返さずに、エラーが発生した行の関連情報を CTXSYS.DR$INDEX_ERROR に記録します。

※ エラーが発生した索引名、時刻、行の Rowid、エラーメッセージなど従って、Text 索引の同期化処理の実施後や定期的に ビュー CTX_USER_INDEX_ERRORSをもとにエラー情報を確認する必要があります。

※ CTX_USER_INDEX_ERRORS は CTXSYS.DR$INDEX_ERROR を参照するビューです。なお、確認した後不要なエラー情報について、定期的に削除する必要があります。以下の SQL で定期的にエラーのビューをクリアするようにしましょう。

SQL> delete from CTX_USER_INDEX_ERRORS;

まとめ

今号では Oracle Text をご紹介しました。Oracle Text は追加のオプション・ライセンスなしで利用できる機能となりますので、文書情報(例えば、インターネット上に点在する膨大な情報)から、必要な情報を効率的に探し出すようなサービスを開発する際に、Oracle Text の導入をぜひ検討してみてください。

参考情報

(オラクル事業部 グローバル・アライアンス&サポート・サービス担当 喬)

Oracle Text について