mysqlftppc 紹介

Post on 03-Jul-2015

3.491 views 1 download

description

mysqlftppc の背景について。プロジェクトページはこちら。 http://mysqlftppc.wiki.sourceforge.net/

Transcript of mysqlftppc 紹介

mysqlftppc 紹介

川井 浩陽

2009-02-12

まず

mysqlftppc = MYSQL Full-Text Parser Plugin Collection

サーバに組み込んで使います。Cで書かれています。

http://mysqlftppc.wiki.sourceforge.net/

MySQL full-text search

SELECT * FROM hoge WHERE MATCH(t) AGAINST(“hogehoge”)

SQL の関数として導入されています。

http://dev.mysql.com/doc/refman/5.1/en/fulltext-search.html

MySQL full-text search

Natural language mode

「この文章に近い文章を見つける」というモード

二つの「文章」を比較して検索結果に含めるかどうかを判断する。

Query Expansion 機能(「ひょっとして~」)

SELECT * FROM hoge WHERE MATCH(t)AGAINST(“The quick brown fox jumps over the lazy dog”);

SELECT * FROM hoge WHERE MATCH(t)AGAINST(“The quick brown fox jumps over the lazy dog”WITH QUERY EXPANSION);

MySQL full-text search

Boolean mode

「この単語は含むがこの単語は含まないものを見つける」というモード。

文章に含まれるトークン群が条件式を満たすかどうか

条件式を表現するための Boolean syntax

SELECT * FROM hoge WHERE MATCH(t)AGAINST(“+hoge -geho” IN BOOLEAN MODE);

SELECT * FROM hoge WHERE MATCH(t)AGAINST(“+(hoge geho) -ab” IN BOOLEAN MODE);

しかし問題もある

トークンの抽出ロジック

実用上使えるのは latin1 のみ。

内部に ctypes という文字種別の辞書を持っている。

「普通の文字*1」の連続を探し出してトークンとする。

この辞書はUnicode以前に整備されたもので、Unicodeにある文字種定義とは全くの別物。

STOPWORDS頻出単語で注目すべきではなく、無視する単語のこと。

基礎にしている参照元のリスト(英語)はあるが、作者の趣味で変更されている(デフォルト)。

ft_min_word_len4文字(デフォルト)より短い文字列は全て無視

*1)普通の文字か _ の連続

しかし問題もある

一般的な全文検索と比べて処理が足りない

Stemming

Unicode collation algorithm の実装が不完全

そうだPLUGINに行こう

MySQL plugin interface

MySQL 5.0 以前

もともと pluggable だった。

MyISAM, InnoDB などサーバ内部に組み込み済みの storage engine を切り替えられた。

UDF (User Defined Function)は、外部の shared library を組み込むことができる(*2)。

MySQL 5.1 で plugin interface が整備される。

*2)http://dev.mysql.com/doc/refman/5.0/en/create-function-udf.html

CREATE FUNCTION metaphon RETURNS STRING SONAME 'udf_example.so';

MySQL plugin interface

種類(5.1以降)

Storage engineテーブル領域を管理する

Fulltext parser全文検索で使用するパーサを追加する

UDF (User Defined Function)SQL関数を追加する

Daemonmysqld プロセス内でデーモンとして動作するスレッド

Information schemaメタデータ管理用の特殊なデータベースに対する操作を通して呼び出されて動作する。

MySQL plugin interface

種類(6.0以降)

AuditEvent(*1)が処理されるときに呼び出されて動作する

ReplicationMySQLのレプリケーションI/O に同期して処理をする(たぶん)。今現在サンプルなし。

*1) MySQL 6.0 からの新機能。CREATE EVENT でイベントを登録する。

Full-text parser plugin interface

text SQLparser

TABLE FULL-TEXTINDEX

Full-textParserPlugin

(tokenize)

Full-textTextfeed

Full-textTokenfetch

MySQL では全文検索エンジンはこのように構成されている

Pluginはここ

CREATE TABLE hoge (t TEXT,FULLTEXT(t) WITH PARSER geho

);

Full-text parser plugin interface

FTPARSER Plugin がやることは、テキストから検索インデックス用のトークンを抽出することだけ。

Natural language mode, boolean mode などの情報はサーバから渡される

しかし Plugin は MySQL 5.1 以降

MySQL 5.0 の人はどうしているか

Senna / tritonn

全文検索エンジンSenna+そのMySQLへのバインディングtritonn

MySQL 5.0 に対するパッチの形で配布。

SQL 構文を拡張

BOOLEAN MODE の構文は Senna の構文で、MySQL標準仕様の拡張に相当。

CREATE TABLE hoge ( t TEXT, FULLTEXT INDEX USING NGRAM (t) )

mysqlftppc

トークンの抽出方法もいろいろあります

現在以下の plugin があります。

bigram

mecab

space

suffix

Snowball

全ての plugin で Unicode normalization が使えます(デフォルト無効)

mysqlftppc bigram plugin

概要

文字2グラムを使います

MySQL 検索規則

Natural Language Mode は実行できますが、その解釈は難しいです。使いません。使わないでください。

Boolean Mode では原則的に常にフレーズ検索を行います。「東京都」という文字列は「東京」「京都」の二つの連続トークン列(フレーズ)を探すことになります。

mysqlftppc mecab plugin

概要

形態素で検索したい場合

mecab ライブラリとリンクしていいます

日本語の文章を扱うなら、難しいことを言わないのであれば、これがいいです

MySQL 検索規則

Natural Langauge Mode では検索文を形態素解析します

Boolean Mode ではフレーズクエリ指定された文字列は形態素解析します。それ以外は形態素での条件指定と解釈します。

mysqlftppc space plugin

概要

空白文字区切りでトークンを抽出します

デフォルトのパーサよりもさらに機械的で、空白以外は全てトークンに含めます。デフォルトのパーサは漢字などは除去します。

MySQL 検索規則

デフォルトのパーサとほぼ同じと考えて構いません

mysqlftppc suffix plugin

概要

Suffix Array に触発されて作りました。

全ての suffix をトークンとして抽出します

MySQL 検索規則

Natural language mode は実行できますが、解釈は難しいです

Boolean mode では常に先頭一致で検索します。

mysqlftppc snowball plugin

概要

Snowball ライブラリとリンクします

デフォルトのパーサに stemming の前処理を加える

たとえば laughing が含まれる文章を laugh で検索できる

各言語用のパーサに切り替えられる

MySQL 検索規則

デフォルトのパーサと同じと考えて構いません

Installation

fthoge.so というファイルひとつだけ。

configure script

mysql_config を使ってインストール先を決めます。明示的に指定してもかまいません。

prefix は指定しません。指定しても使われません。どうせファイルひとつだけですし。

mysql_config が $PATH に入っていれば ./configure; make; make install 以上終了です。

Installation

MySQL への組み込み。

INSTALL PLUGIN hoge SONAME 'libfthoge.so'

SHOW PLUGIN

全文検索インデックスの作成

CREATE TABLE hoge (t TEXT, FULLTEXT(t) WITH PARSER hoge)

データの投入と検索

INSERT INTO hoge VALUES(“geho”)

SELECT * FROM hoge WHERE MATCH(t) AGAINST(“geho” IN BOOLEAN MODE)

開発経緯

なんとなく検索したい要求が(数だけはたくさん)ありそうだった

検索って何?を聞いてみると

日本語の自然文検索(全文検索)

日付範囲を絞り込みたい

~が~のものを検索したい(属性検索)

よくわからないけどとりあえず「検索」と発言する人達

検索でイメージするものには人によってばらつきがあります。

実装もさまざまあります。

全文検索エンジン

全文検索エンジン

文章(全文)を対象として文字列で条件に適合するかどうかを検査する。Full-text search

Namazuあるファイルがテキストを含んでいるとして、そのテキストを検索可能にする。

検索した結果はファイル一覧。

Rast, HyperEstraierある文書がテキストを含んでいるとして、そのテキストを検索可能にする。

検索した結果は文書ID一覧。

ついでに(全文検索できない)プロパティを追加管理できる

たとえば電子メール

本文に~~が含まれているものを検索したい

受信日時が~~のものを検索したい

送信者が~~のものを検索したい

件名が~~のものを検索したい

件名に~~が含まれているものを検索したい

…あれ?

全文検索エンジンから

テキスト=

ファイル

プロパティ

プロパティ

プロパティ

プロパティ

検索エンジンへ

何か(検索単位)

プロパティ

受信日時

件名

本文

こういった管理体系を実現するには…?

検索エンジン

たとえば Lucene

検索対象は属性(プロパティ)を持っている。

その属性は全文検索の対象となるテキストかもしれない。

そうじゃないかもしれない。数値かもしれないし、日付かもしれない。

検索エンジン

Solr / Lucene

Lucene は検索エンジンを管理する Java ライブラリ

通常あるディレクトリ以下にインデックスファイルを構築する

ファイル形式は独自形式

設定しだいで Analyzer を差し替え可能

Solr は Lucene を Web 経由で呼び出しできるようにするサーブレット

Lucene 自体はレプリケーションやマルチマスタなどの機能は持っていないので、Solr 側で制御したりする

たとえば Tomcat 上に乗せる

通信プロトコルは多彩

PHP native, POST, XML ベースの通信など

検索エンジン

HyperEstraier

2gram で分解して、転置インデックスを作る

扱えるテキスト(全文検索)は一つ。そのほかに属性が管理できる。

Estmaster という Web サーバデーモンが付属している

C で実装されている

ノード API で分散処理することもできる

文字列に対して独自の正規化が行われる

属性検索

属性検索は意外と大変。

数値比較

日付比較

カレンダーを引く計算が必要(Timezone)。

Timestamp は不十分。負数や小数の問題。

例)生年月日

文字列比較

~で始まる、~で終わる、辞書順(COLLATION)

実は属性検索のニーズが多い

Windows NTFS のファイル管理を思い浮かべてください。

RDBMS

MySQL

検索単位は行

検索対象は属性(カラム)持っている。

SQL で検索する

型に応じた検索条件が指定できる

SELECT * FROM hoge WHERE geho1=”foo”AND geho2 < 4AND YEAR(geho3) = '2009'

検索エンジン vs RDBMS vs XMLDB

属性の追加(スキーマ)

検索エンジンは多くの場合属性は動的に追加できる

RDBMS は CREATE TABLE でスキーマ定義が必須

RDBMSに対するスキーマレスといえばXMLDB

否定で検索するか~?

検索エンジンは「~がない」で検索できない。しない。

RDBMSではNULL条件指定に相当するが…効率悪い

属性が構造体だったらどうする?

そのまま行に押し込むにはXMLDB(XQuery)

RDBMS は正規化の過程で別テーブルに変化する

キーワードとプロダクト

全文検索エンジン

検索エンジン

属性検索

RDBMS

MySQL

XML

XMLDB

key/valuedatabase

LuceneBerkeley DB

memcached

Tokyo Cabinet

Hyper Estraier

Oracle

Namazu

そんなこんなで mysqlftppc

MySQL を使いたかった

運用実績(手順)

既にたくさんの MySQL を運用している

開発環境

ライブラリやプロトコル

データの信頼性

Recovery

Replication

Backup

Senna でもいいけど、パッチ管理は面倒

せっかくだから 5.1 plugin ⇒作るしかFTPARSER

mysqlftppc

なんでこんなにたくさんの種類があるのか

「全文検索」というものの性質

全文検索

一般的なケース

保存対象は自然言語の文章

検索も自然言語

ある検索条件から得られる結果が「期待」するものであるためには

「期待」はケース・バイ・ケースです。ほとんど気持ちの問題。

一般的な解というものはありません。

さまざまな戦略が考えられます。

Tokenize

戦略の一つとして、文章の文字列を一度「トークン」という単位に分解することからはじめる実装は多いです。

MySQL もこの戦略をとります。

Tokenize

「適切なトークン」は言語の特性に依存

まず文字で表現されていることが前提。

Unicodeでは文字の正規化に関する仕様があり、要求と合致すれば大変便利。Unicode normalization

日本語の全角半角カナの表記ゆれは、このレベルで吸収することもできる。

英語などはスペースで区切れば、大体オーケー。

一部特殊なケースもある(ハイフンでつながっているなど)

検索時のためにもう少し処理しないといけない場合もある

現在日本語に対してトークンを得る手法で実用的なものは、大雑把に 2 種類

形態素

文字N-gram

形態素

形態素解析の前提知識

まず「形態素」というものがあると仮定するのが前提

そうではないという考え方を否定するわけではない。

日本語では日本語の品詞で分類された形態素を使うのが一般的

品詞体系は一つじゃない。

実用上使いやすいであろうという基準で整備されてきたものの一つに naist-jdic がある。

日本語の文章は品詞体系に沿って形態素に分解

Mecab

確立を使って尤もらしい分解を行う

「辞書」に形態素の知識や確立に関する知識を持つ

文字n-gram

文字 n-gram の前提知識

文章は文字の羅列で表現されている

文字の羅列をうまく検索できるといい

文字を単位として、とにかく分解しよう

文字 2 グラム

「本日は晴天なり」

「本日」「日は」「は晴」「晴天」「天な」「なり」

形態素解析か文字ngramか

Mecab

辞書の使っている品詞体系と自分の思惑とを合致させておくことが重要

検索漏れ?のように錯覚してしまうこともある

確立で処理しているので、間違うこともある

解析したい日本語と、辞書の学習した日本語の性質が異なっているかもしれない

普通に検索漏れとして見える

文字ngram

とにかく文字列に合致したものが全て見つかる

「それじゃない」と感情的に思えてしまうことも多々ある

「京都」で検索すると「東京都」が見つかる

mysqlftppc

なんでこんなにたくさんの種類があるのか

「全文検索」というものの性質

日本語

形態素かngramか:両方用意したので、使い分けてください

キーワードで検索

「キーワード」で検索したい場合。

「キーワードの羅列を保存して検索できるようにする」という設計もアリ。全文検索。

キーワードを空白区切りで連結する。

キーワードは空白を含むかもしれない。→エスケープシーケンスが必要。

組み込みパーサでは無理。

mysqlftppc space plugin を使う

Senna / tritonn では delimited に相当。

mysqlftppc

なんでこんなにたくさんの種類があるのか

「全文検索」というものの性質

日本語

形態素かngramか:両方用意したので、使い分けてください(bigram, mecab)

キーワード

space plugin 使ってください

stemming

活用形を含めて検索したいケースがある

He lives in Tokyo.

I live in Tokyo.

“live in Tokyo” で検索し、両方見つけたい。

Snowball という良いライブラリがある

多言語対応(欧米)

mysqlftppc

なんでこんなにたくさんの種類があるのか

「全文検索」というものの性質

日本語

形態素かngramか:両方用意したので、使い分けてください(bigram, mecab)

キーワード

space plugin 使ってください

Stemming

Snowball plugin 使ってください

full-text parser

Built-in parser Plugin parser

engine

text

parser->parse()

param->mysql_add_word()

param->mysql_parse()

* built-in parser

ft_min_word_lenft_max_word_lenft_stopword_file

full-text parser

Built-in parser Plugin parser

engine

text

parser->parse()

param->mysql_add_word()

param->mysql_parse()

* bigram parser* mecab parser* space parser* suffix parser

ft_min_word_lenft_max_word_lenft_stopword_file

full-text parser

Built-in parser Plugin parser

engine

text

parser->parse()

param->mysql_add_word()

param->mysql_parse()

* snowball parser

ft_min_word_lenft_max_word_lenft_stopword_file

解決できていない問題

スコアリング

ならび順の制御

おそらく UDF で制御することになる(効率の問題)

Natural language mode

半分以上ヒットしたら、そのキー情報は使わない

Query expansion

独自カラーは結構強い

内部でどんな処理が起こっているのか伺いにくい

次期バージョンで UDF 追加予定

MyISAM しかまだ対応してない

以上

Questions?