MySQL+Sennaバインディング拡張パッチ
このパッチは、有限会社未来検索ブラジルで開発されているオープンソースの全文検索エンジン「Senna」用に用意されている MySQL バインディングを拡張し、さらに便利に利用しようというものです。
現在 revision 115 の修正にまでキャッチアップしています。
2006/7/21
未来検索ブラジルの開発チームを初めとするSenna の開発に関わる方々の努力により、ここでご紹介しているメガパッチが r191 でついに本体に取り込まれました。みなさま、本当にお疲れさまでした。この場を借りて御礼申し上げます。
http://lists.sourceforge.jp/mailman/archives/senna-dev/2006-July/000245.html
ドキュメントについては随時更新していきます。
著作権表示
パッチ自体の著作権はグリー株式会社に帰属します。 原ソースコードにパッチを適用することは、適用者を主体とする原著作物への改変であるとし、その行為および行為による生成物の扱いは原ソースコードの著作者の権利に基づくものとします。
補足 (2006/4/19)
「なんだ、オープンソースとか言っていながら OSS ライセンスで提供していないではないか」というような誤解があるといけないので補足させてください。
上にある「原ソースコード」という用語の定義があいまいだ、というご指摘はもっともです。ここで述べている「原ソースコード」とは「パッチ」を当てる対象となるソースコードのことで、「パッチ」は「原ソースコード」ではありません。
上記の意味するところは、「パッチ」として提供しているファイル自体は弊社著作物という扱いになりますが、たとえばパッチを Senna のオリジナルのソースコードに当てることは、Senna を改変しているということになりますし、パッチを Senna に当てた後のソースコードの著作権は Senna の作者の方が保持しますよ、ということです。
つまりライセンスに関して言えば、端的に言うと Senna の場合でしたら Senna のライセンスに従いますし、MySQL であれば MySQL のライセンスに従うということになります。
免責事項
このパッチをご利用になったことにより発生した、直接的もしくは間接的な損害について、小泉守義およびグリー株式会社は一切の責任を負わないものとします。
内容
configure.in のクリーンアップ
具体的には
libmecab および libsenna の自動検出
mecab-config および senna-cfg のようなビルドコンフィギュレーションスクリプトにパスが通っており、--with-mecab や --with-senna に値が指定されていなければ、それらのスクリプトより自動的にインクルードパスやライブラリパスを取得し、ビルドを設定します。
インストールプレフィックス指定オプション (--with-mecab / --with-senna)
--with-mecab=[libmecab のインストールプレフィックス]
--with-senna=[libsenna のインストールプレフィックス]
のように、利用するライブラリのインストールプレフィックス (例: /opt/senna, /usr/local) を明示的に指定することができるようになりました。
例:
./configure --prefix=/usr/local/mysql --with-extra-charsets=complex
--with-senna=/usr/local --with-mecab=/usr/local
拡張 SQL 構文のサポート
CREATE TABLE / CREATE INDEX 句の拡張
生成する Senna のインデックスタイプを指定できるようになりました。normalize (NFKC) の処理の on / off も指定できます。
(例) CREATE INDEX test ( id INTEGER AUTO_INCREMENT, PRIMARY KEY (id), text TEXT NOT NULL, FULLTEXT INDEX USING SENNA,NGRAM,NORMALIZE (text) );
USING SENNA をはずせば MySQL の素の FULLTEXT INDEX も利用できるようになっていますが、あまりそういった機会はないでしょう。
SHOW INDEX 句の拡張
CREATE TABLE / CREATE INDEX の拡張に伴い SHOW INDEX 句も拡張して、使用しているインデックスの種類を調べることができるようになりました。
mysql> SHOW INDEX FROM test; +-------+------------+----------+- ... -+--------+------+--------------------------------+---------+ | Table | Non_unique | Key_name | | Packed | Null | Index_type | Comment | +-------+------------+----------+- ... -+--------+------+--------------------------------+---------+ | test | 0 | PRIMARY | | NULL | | BTREE | | | test | 1 | text | | NULL | YES | FULLTEXT,SENNA,NORMALIZE,NGRAM | | +-------+------------+----------+--... -+--------+------+--------------------------------+---------+ 2 rows in set (0.04 sec)
SHOW TABLE STATUS 句の拡張
SHOW TABLE STATUS 句 によって、あるテーブルで使われている Senna の転置テーブルや語彙テーブルのレコード数の合計や、インデックスファイルのサイズを知ることができるようになります。複数の全文検索インデックスがあったときにはあまり意味がありませんが...。
+-------+--------+ ... -------+----------------+----------------+--------------------+---------+ | Name | Type | ... k_time | Create_options | Senna_key_size | Senna_lexicon_size | Comment | +-------+--------+ ... -------+----------------+----------------+--------------------+---------+ | test1 | MyISAM | ... | | 0 | 0 | | | test2 | MyISAM | ... | | 0 | 0 | | | test3 | MyISAM | ... | | 0 | 0 | | | test4 | MyISAM | ... | | 0 | 0 | | | test5 | MyISAM | ... | | 0 | 0 | | +-------+--------+ ... -------+----------------+----------------+--------------------+---------+
次のカラムが追加されています。
- Senna_keys_size
シンボル表 (.SEN) のレコード数の合計を示します。
- Senna_keys_file_size
シンボル表 (.SEN) のファイルサイズの合計を示します。
- Senna_lexicon_size
語彙テーブル (.SEN.I) のレコード数の合計を示します。
- Senna_lexicon_file_size
語彙テーブル (.SEN.I) のファイルサイズの合計を示します。
- Senna_inv_seg_size
転置テーブルのバッファ (.SEN.i) のファイルサイズを示します。
- Senna_inv_chunk_size
転置テーブル (.SEN.i.c) のファイルサイズを示します。
XXX: 2^32 - 1 を超える値は正しく取得できません。
その他
Senna を組み込んでいない素の MySQL を、同じソースツリーからビルドできる
特に利用する上でベネフィットはありませんが、アップストリーム (本家) にフィードバックする際に、一助にはなることを期待しつつがんばってみました。 注意深く diff を見ながら、元のソースからは
#ifdef ENABLE_SENNA ... #endif
で、徹底的に Senna 独自部分の分離を行いました。
configure を --with-senna なしで走らせることにより、Senna バインディングは組み込まれなくなります。
パッチ適用方法
1. senna にパッチを当てる
以下のパッチを当てます。
パッチ対象はソースツリーのルートに対する相対パスとなっていますので -p0 オプションを使用してください。
% cd senna-trunk % zcat senna-misc-info-retrieval-patch-200604101928.diff.gz | patch -p0
senna 側を改造するのはできれば避けたかったのですが、実際運用で使いたい情報を取るのに行儀悪く構造体をつつくよりはクリーンな形でフィードバックできるのではないかと考えたため、そうしました。
2. Senna バインディングパッチを適用した MySQL にパッチを当てる。
素の MySQL に対しては Senna 付属のパッチを当てた後に以下のパッチを当てます。つまり、都合 2 回パッチを当てることになります。
パッチはソースツリー同士の比較をしたものとなっていますので、MySQL ソースツリーの中に chdir した後で -p1 オプションを使用してパッチを当ててください。
% cd mysql-4.0.26 % zcat mysql-4.0.26-senna-ext-200604101928.patch.diff.gz | patch -p1
パッチを適用後、autotools により生成されるスクリプトの再生成が必要です。autoconf (2.59)、automake (1.9) は最新版を使ってください。
% libtoolize -c -f % aclocal % autoheader % automake -c -a -i % autoconf
以上の操作を行った後に、sql/sql_yacc.yy を touch します。
% touch sql/sql_yacc.yy
補足 (2006/4/27)
改造のポイント
Senna側
Senna には具体的には次の関数を追加、もしくは拡張しています。
追加した関数
- sen_io_size()
sen_rc sen_io_size(sen_io *i, off_t *size)
i で示されたブロック I/O 対象のサイズを取得します。
- パラメータ
パラメータ名 入出力 説明 i in 対象となるデータ実体 (ファイル) size out 結果を格納する off_t へのポインタ - 戻り値
成功時に sen_success
- パラメータ
- sen_inv_info()
sen_rc sen_inv_info(sen_inv *i, off_t *seg_size, off_t *chunk_size)
i で示された転置テーブルで利用される各種データのサイズを取得します。
- パラメータ
パラメータ名 入出力 説明 i in 対象となる転置テーブルのインスタンス seg_size out 転置テーブルのバッファのサイズを格納する off_t へのポインタ chunk_size out 転置テーブルのサイズを格納する off_t へのポインタ - 戻り値
成功時に sen_success
- パラメータ
拡張した関数
- sen_sym_info()
- sen_index_info()
それぞれ追加の情報が取得できるよう引数を増やしています (詳しくはソースを見てください :))。引数だけでゴテゴテしてしまってあまりスマートではなくなってしまったのですが、この後どう持っていくかはお任せします :-p
注意事項、連絡事項、その他
- #include "config.h" を追加しているのは、_FILE_OFFSET_BITS が他のシステム由来のヘッダファイルが読み込まれる前に必ず定義されている状況を作らなければならかったからです (これに気づかなくて随分訳のわからない SEGV に悩まされました…)。個人的に思うのは、すべての .c ファイルの先頭で
#ifdef HAVE_CONFIG_H #include "config.h" #endif
しておくのがベストプラクティスかな、なんてことですが…。
MySQL 側
随分昔にやったことなので、ほとんど忘れました…。
- 現在の MyISAM の .MYD ファイルのバイナリフォーマットと互換性を維持するためにビットマスクを入れ替えたりだとかちょっとトリッキーなことをしています。
- handler API においてインデックスの種類を示すビットマスクの内容が、handler SPI (API の間違いじゃないです) から MyISAM API に処理が渡る過程で一部失われるようなことになっているのが MySQL の構造としてダメなところなのですが (4.1 以降では直っている?)、それを乗り越えるために一部 MySQL API を強引に書き換えたりだとか傍目からはヒドいことをやったりしています。
コメント
ご意見等ございましたら <labs-feedback@gree.co.jp> までお願いいたします。