Oracleテキストの仕組み

先日、Oracle Textにちょっと調べていて
なるほどなーって思ったので少し書いてみます。

OracleTextは前文検索が出来るOracleが提供している機能のひとつで、
Enterprise Editionはもちろんのこと、
Standard Editionでもついているので無償で利用できます。

さて、全文検索とは・・・


いわゆる「部分一致検索」とか「あいまい検索」とか言われるものですね。
例えばこのエントリーのタイトル【Oracleテキストの仕組み】では
中間に入っている【テキスト】という文字で検索ができること。
一般的なSQLのtitle LIKE '%テキスト%'にあたります。


まぁ、このLIKE検索でも機能的な役割は果たしますが
LIKE検索で%を前後につけるとINDEXが効かなくなるので
フルスキャンが走り、大変コストのかかる検索になります。
そこでこのOracleテキストの登場です。
MySQLにはFULLTEXTインデックスという似たようなものがありますね。

このOracleテキストを対象カラムに設定してSQLのWHERE句に
【CONTAINS(title, 'テキスト') > 0】という感じに
CONTAINS関数にカラム名と検索文字列を渡してあげます。
「> 0」がないとダメなので気をつけましょう。

ただ、いくらOracleテキストといえ、何千万・何億という
検索対象だとやはりちと、遅い。
そういう場合は全文検索用のミドルウェアであるApache Solrなどと
併用すると良いでしょう。
左のサイドバーのサイト内検索で
「Solr」と検索すれば以前の記事が見つかると思います。



さてOracleテキストの仕組みです。

単一項目にOracleテキストを付与すると内部で
複数のオブジェクトが生成されます。
仮に今回はENTRYというテーブルのTITLEカラムに
ENTRY_TITLE_ORATEXT_IDXという名前でOracleテキストを
作ったとします。

そうすると以下の3つが出来ます。

ENTRY_TITLE_ORATEXT_IDX
ENTRY_TITLE_ORATEXT_IDX$I
ENTRY_TITLE_ORATEXT_IDX$X



これらの内容はこんな感じ。


●ENTRY_TITLE_ORATEXT_IDX
これがOracleテキストのメインです。
このインデックスオブジェクトを経由して
残りのインデックスが呼ばれます。


●ENTRY_TITLE_ORATEXT_IDX$I

「$I」が付いたオブジェクト。
これは転置インデックスとなっています。
インデックスを付けたカラムの文字列を
トークンとして分解します。
基本的には日本語は2文字分割、英語は単語分割されます。
英語はスペースやハイフンなどの記号で単語化できますが
日本語は単語にするのが難しいので。。。

例えばこのエントリーと一つ前のエントリーの
タイトルである、

Oracleテキストの仕組み
OCNのネットワーク障害

からトークンを作る場合は以下のように分解されます。

  • Oracle
  • テキ
  • キス
  • スト
  • トの
  • の仕
  • 仕組
  • 仕み
  • OCN
  • のネ
  • ネッ
  • ット
  • トワ
  • ワー
  • ーク
  • ク障
  • 障害

こんな感じです。
どういつのトークンがあった場合は1つのレコードにまとめられます。
カラム構成は以下のような感じ。

・対象のトークンが含まれる実レコードの個数、
・実レコードが含まれるアドレス範囲、
・実レコードの場所

●ENTRY_TITLE_ORATEXT_IDX$X

これはトークン表に対するビットマップインデックスです。
トークン表をインデックスにすることにより
高速でデータの有無を判断して、
決められた範囲・レコードの場所(ROW_IDとかかな?)から
実レコード見つけるので高速でHITするわけです。


なかなか考えられている仕組みですね。
ちょっと関心しました。
2文字区切り(N-gram検索)なので
日本語の精度は微妙ですが、設定次第では辞書情報を持たせてより
精度の高い検索が出来ますが労力もかかります。

絵で見てわかるOracleの仕組み (DB Magazine SELECTION)

絵で見てわかるOracleの仕組み (DB Magazine SELECTION)