Full Scanを速くしちゃう~Oracle Text編~その2

投稿日: 2010年11月10日

<Full Scanを速くしちゃう~Oracle Text編~その2>
ペンネーム: グリーンぺぺ

前回はOracle Textを使用することにより中間一致検索を秒殺する
テクニックを紹介した。どうしてOracle Textは速いのか?
今回解説する。全文検索について知ってるよという方は
今回は読み飛ばして下さい。

■Oracle Textの使い方手ほどき編
前回Oracle Textを何の前触れもなく使ってみたので少し解説を交え
ながら、Oracle Textエンジンを利用した検索を行ってみる。

□手順1:プリファレンスの作成

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

プリファレンスとはOracle Textによる索引の作成方法に影響するオプションの
パラメータのことを指す。作成するプリファレンス名とプリファレンス型の名前
を指定する。今回は日本語テキストから*1トークンを抽出する*2レクサーを指定
する。
*1トークン
単語や記号の最小単位
*2レクサー
字句解析ルーチン

□手順2:lyric列に索引作成

SQL> CREATE INDEX ix_lyric ON ranking(lyric)
     INDEXTYPE IS ctxsys.context
     PARAMETERS('lexer my_lexer');

先ほど作成したプリファレンスを使用して索引を作成する。

□手順3:lyric列に’バイバイ バイヨン’が含まれる行を検索
Contextタイプを利用した索引を利用して全文検索を行う場合、
contains句を利用して検索を行う。

SQL> select TITLE,ARTIST from ranking where contains(lyric,'バイバイ バイヨン')>0;
TITLE           ARTIST
--------------- ---------------
虹色のバイヨン  氷川きよし

仕組み的にはこの3ステップでOracle Textの利用が可能である。
とっても簡単!!使ってみたい!!という方に是非試して頂きたい。

■Oracle Text運用編
とっても簡単に使えるOracle Textだが、実際に本番環境として使うには
いろいろ考慮する必要がある。

□注意点その1
新規行が追加されたり、検索カラムの変更削除が行われても上記の索引作成
手順では索引の同期は行われない。よって索引の同期を行う必要がある。

SQL> insert into ranking values
     (13,'Re:birth','Acid Black Cherry','林保徳','林保徳'null,
     '静かな夜は大嫌い 不安が騒いで眠れなくなる...);

SQL> select TITLE,ARTIST from ranking where contains(lyric,'不安が騒いで眠れなくなる')>0;

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

--索引の同期後、検索ヒット可能となる
SQL> exec ctx_ddl.sync_index('IX_lyric');

SQL> select TITLE,ARTIST from ranking where contains(lyric,'不安が騒いで眠れなくなる')>0;

TITLE           ARTIST
--------------- --------------------
Re:birth        Acid Black Cherry

10gR1以降のヴァージョンであれば、索引の同期化をon commitで行うか、
一定の間隔で索引の同期化を自動で行うことができる。
on commitにすればDML処理に遅延のおそれがあるので、どのような
タイミングで同期を図るかは調整が必要だ。

--on commitで全文検索索引を同期化する
SQL> CREATE INDEX ix_lyric ON ranking(lyric)
     INDEXTYPE IS ctxsys.context
     parameters('lexer my_lexer sync (on commit)');

SQL> insert into ranking values
     (13,'Re:birth','Acid Black Cherry','林保徳','林保徳'null,
     '静かな夜は大嫌い 不安が騒いで眠れなくなる...);

SQL> select TITLE,ARTIST from ranking where contains(lyric,'不安が騒いで眠れなくなる')>0;

TITLE           ARTIST
--------------- --------------------
Re:birth        Acid Black Cherry

□注意点その2
Oracle Textは音節でトークンを区切って索引を作成するので
音節を途中で切った検索キーワードではヒットしない。

SQL> select TITLE,ARTIST from ranking where contains(lyric,'バイ バイヨン')>0;

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

■まとめ
Oracle Textをうまく使えば全件検索を高速化することができる。
但し、
1)索引の同期化、メンテナンス運用を考慮する必要がある。
2)検索ヒットさせたい語句がヒットしなかったりする。
実際に使用する際にはこの2点を注意する必要がある。