エンタープライズ:特集 2003/07/03 21:24:00 更新

JAVA Developer 2003年6月号より転載
MySQL4の全文検索に迫る

MySQL 4.0のプロダクションレベル4.0.12がリリースされました。MySQL 4.0の目玉機能の1つは、改良された全文検索(Full-text Search)です。もちろん、優れた機能はほかにも追加されていますが……。ここでは、MySQL 4.0の全文検索を例に、データベースの全文検索について考えてみます。
全文検索とは

 そもそも全文検索とは、どんな機能でしょう? イメージとしてつかみやすいのは、Googleなどの検索エンジンによるサービスだと思います。ユーザーが検索したいキーワードを自由に入力し、そのキーワードが含まれるHTMLやPDFなどのドキュメントがリンク情報とともに一覧で表示されるというものです。全文検索は、このようにキーワードを指定して、そのキーワードが含まれるデータを探す機能といえるでしょう。

 全文検索は、任意のキーワードに対して検索を行うため、大量のデータを対象に単純な検索を行うと、効率が悪く、時間もかかってしまいます。このようなことから、多くの全文検索エンジン(システム)では、検索対象のデータに対しインデックス情報を作成し、検索実行時は対象データではなく、インデックス情報を調べ、検索効率を高めています。

データベース(RDBMS)の全文検索

 データベースの全文検索も、基本的な考え方は同じです。データベースにおいて全文検索を実現するには、まず次に示すテーブル作成SQLで「FULLTEXT」を使い、全文インデックス(Full-text indexes)を作るカラム名を指定します。

CREATE TABLE articles (
    id INT UNSIGNED AUTO_INCREMENT
        NOT NULL PRIMARY KEY,
    title VARCHAR(200),
    body TEXT,
    FULLTEXT (title,body));

 この例ではtitleとbodyという2つのカラムを指定していますが、もちろん1つだけ指定することも可能です。MySQLの場合、指定できるカラム型は、CHAR、VARCHAR、TEXTの3つです。カラム型は、データベースによって異なりますが、基本的には文字型が対象になります。またインデックスの作成は、ALTER TABLEを使ってテーブル更新時に行うことも可能です。

 実際の検索は、WHERE句に「MATCH」と「AGAINST」を指定して行います。MATCHには検索対象のカラムを、AGAINSTには検索したいキーワードを'で囲んで指定します。

SELECT * FROM articles
    WHERE MATCH (title,body)
    AGAINST ('database');

あいまい検索LIKEとの違い

 ご存じの方も多いと思いますが、SQLではあいまい検索LIKEを利用できます。%や_といったワイルドカードを組み合わせて柔軟に検索できるのがLIKEの特徴であり、「あいまい検索」と呼ばれる理由です。

SELECT * FROM articles
    WHERE title like "database";

 LIKEの検索は、先頭文字から比較するという条件であれば、インデックスを作成することで高速化できます。

CREATE INDEX title_index
    ON articles (title);

 通常のインデックスは、文字型以外でも指定可能で、MySQLではBLOBも利用可能になっています。また、このインデックスは先に説明した全文インデックスとまったく異なるものです。

 また、全文検索とあいまい検索では検索機能そのものにも大きな違いがあります。全文検索では、AGAINSTで指定する検索キーワードに対し、+や−、*などのオペレータを指定でき、LIKEよりも柔軟に検索できます。複数のキーワードを組み合わせて検索するような複雑な検索は、全文検索のほうがシンプルなSQLで指定できるでしょう。

リスト ft_static.c(一部抜粋)
/* This particular stopword list was
taken from SMART distribution
   ftp://ftp.cs.cornell.edu/pub/smart/
smart.11.0.tar.Z
   it was slightly modified to my
taste, though
 */
  "a's",
  "able",
  "about",
  "above",
  "according",
  "accordingly",
  "across",
  "actually",
  "after",
  "afterwards",
  "again",
  "against",
         :

全文検索で日本語が使えるか?

 便利そうな全文検索ですが、日本語のデータですぐに利用できるかというと、簡単ではありません。まず、MySQLの全文インデックスは基本的に英語のみで、日本語に対応していません。

 すべてのソースコードを調べたわけではありませんが、「stopword」を定義しているリストには英単語しか入っていません。環境変数「ft_stopword_file」があることから、場合によってはここで外部ファイルを指定することで対応できる可能性もあります。ただし、日本語の場合は、全文インデックスの対象となる単語の抽出そのものが大きな課題です。

 いずれにせよ、MySQLで日本語全文検索を実現し、Javaから汎用的に利用するためには、ソースコードのmyisamディレクトリのft_*.cと格闘しなければならないようです。また、文字エンコーディングの対応も考慮しなければなりません。なんとなく罠にはまった感じですが、もう少し調査してその結果をレポートしたいと思います。

関連リンク
▼JAVA Developerホームページ
▼日本MySQLユーザー会
▼MySQLでお気楽全文検索

[松浦 武範,JAVA Developer]

Copyright © ITmedia, Inc. All Rights Reserved.