CentOS に PHP+mroonga(MySQL全文検索) のインストール


全文検索を復習するために mroonga(groonga + MySQL) をCentOSに入れて PHP から利用できるようにしてみました。手順間違えると php-mysql がインストール出来なかったりと結構めんどくさいのでメモを兼ねて記録。

mroonga とは
MySQLで全文検索できます。詳しくは公式を。

構成

  • CentOS5 64bit (32bit だと mroonga がまともに動かないらしい)
  • PHP 5.3
  • MySQL 5.5.21
  • mroonga v2.00 (2012-03-16現在最新)
  • mroonga はストレージモードで稼働


1. リポジトリ追加

wget http://dl.fedoraproject.org/pub/epel/5/i386/epel-release-5-4.noarch.rpm
wget http://rpms.famillecollet.com/el5.i386/remi-release-5-8.el5.remi.noarch.rpm
rpm -Uvh remi-release-5-8.el5.remi.noarch.rpm epel-release-5-4.noarch.rpm
rpm -ivh http://packages.groonga.org/centos/groonga-repository-1.0.0-0.noarch.rpm

remi の有効化

vi /etc/yum.repos.d/remi.repo
[remi]
name=Les RPM de remi pour Enterprise Linux $releasever - $basearch
#baseurl=http://rpms.famillecollet.com/enterprise/$releasever/remi/$basearch/
mirrorlist=http://rpms.famillecollet.com/enterprise/$releasever/remi/mirror
# ↓ 0 を 1 に変える
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi
failovermethod=priority
※ [remi-test] は有効にしないこと

パッケージ更新

yum update

2. PHP, MySQL, mroonga のインストール

PHPは必要最低限のモジュールしか入れてないので、足りない分は追加してください。

yum install mysql-server php-devel php-mysql php-mbstring
yum install mysql-mroonga

3. MySQL設定

my.cnf 編集

vi /etc/my.cnf
[mysql]
default-character-set=utf8

[mysqld]
skip-character-set-client-handshake
character-set-server=utf8
mroonga_default_parser=TokenMecab

↑の設定では構文解析(mroonga_default_parser) に Mecab(いわゆる わかち書き) を使ってます。変えたい場合は公式の↓あたりを見てください。

http://mroonga.github.com/ja/docs/userguide/storage.html
3.3.1.3. 全文検索用パーサの変更

MySQLの起動 と plugin インストール

/etc/init.d/mysql start
mysql -u root -e " INSTALL PLUGIN mroonga SONAME 'ha_mroonga.so'; CREATE FUNCTION last_insert_grn_id RETURNS INTEGER soname 'ha_mroonga.so'; "
※ 上の mysql -u root.... は1行です

mroonga が有効になったか確認

mysql -u root
show engines;
省略
| mroonga | YES | CJK-ready fulltext search, column store   | NO   | NO | NO |
※ ↑の行があれば大丈夫

4. 動作確認

ちゃんと動くか確認してみます。test データベースに hoge テーブルを作って、何レコードが insert

use test;

create table hoge ( id int primary key auto_increment, content varchar(255), fulltext index(content)) engine = mroonga default charset utf8;

insert into hoge(content) values("全文検索はめんどうだな");

insert into hoge(content) values("全文検索はほげほげです");

insert into hoge(content) values("全文検索は、はげです");

insert into hoge(content) values("全文検索はバルス");

insert into hoge(content) values("あげあげほげほげ");

全文検索できるか select

select * from hoge where match(content) against("ほげ");

+----+-----------------------------------+
| id | content                           |
+----+-----------------------------------+
|  2 | 全文検索はほげほげです            |
|  5 | あげあげほげほげ                  |
+----+-----------------------------------+
2 rows in set (0.00 sec)

できました。

5. 性能確認

動くだけじゃ意味がない(like 検索でいいじゃん、ってことに…)ので、mroonga で 100万件入れたテーブル(さっきの hoge 流用)と、innodb で 100万件いれたテーブル(hoge2)を作って性能比較をしてみます。

innodb テーブル用意 ( hoge2 )

create table hoge2 ( id int primary key auto_increment, content varchar(255)) default charset utf8;

100万件突っ込む方法ですが、PHPのスクリプト置いてテーブル名を変えて実行します。

スクリプト作成(insert.php)

<?php
// 開始時間記録
$start = time();

// 生成する文字列設定とか
$tableName = 'hoge';  // ← ここがテーブル名
$numOfRecords = 1000000;  // ← 100万件。変えたければここを変える
$keyword = '私は PHP 全文検索 漫画 焼肉 年金 社畜 タバコ (´・ω・`) 説明しろ '.
           'あなたは ごちゃごちゃ バカなの システム開発 フォロー tweet '.
           'ギブアップ 24時間 働けますか 呪われる かっぱ寿司 プログラム '.
           'ラーメン 5億 差し上げよう おすすめ android iphone カツ丼 '.
           'しましょう Facebook Google+ カルビ焼肉 やきそば 帰ったらしい';
$keywordList = explode(" ", $keyword);
$numOfKeyword = count($keywordList);

// DB接続
$db = new mysqli("localhost","root","");
$db->query("use test");
$stmt = $db->prepare("insert into ".$tableName."(content) values(?)");

$count = 0;
for($i=0; $i<$numOfRecords; $i++){
    ++$count;
    $str = '';
    for($k=0; $k<10; $k++){
        $index = rand(0, $numOfKeyword - 1);
        $str .= $keywordList[$index];
    }
    $stmt->bind_param("s", $str);
    $stmt->execute();

    if($count == 10000){
        echo ($i+1) . " record inserted\n";
        $count = 0;
    }
}

$db->close();

// 何秒かかったか
echo (time() - $start) . " seconds\n";

$keyword は、TwitterとかG+とかで、ちら見した文字を適当に入れてます。深い意味はありません。。

PHP実行
最初は、hoge テーブルのまま mroonga に突っ込む

php insert.php

1万件ずつ ? record inserted と標準出力してます。最後に ? seconds って出たら終わり。

次は hoge2 テーブルで。insert.php を編集して hoge2に。

// 生成する文字列設定とか
$tableName = 'hoge2';  // ← ここがテーブル名

編集したら実行。

php insert.php

最後に ? seconds って出たら終わり。こっちは結構かかると思います。

insert 結果

mroonga 162秒
innodb 1082秒

あくまで自分の環境ですが、7倍ぐらい mroonga 速いです

次は、全文検索してみます。

mysql -u root
use test;
select count(*) from hoge;
+----------+
| count(*) |
+----------+
|  1000000 |
+----------+
1 row in set (0.00 sec)

select * from hoge limit 10;
+----+-------------------------------------------------------------------------------------------+
| id | content                                                                                   |
+----+-------------------------------------------------------------------------------------------+
|  1 | tweetFacebook年金ごちゃごちゃやきそば説明しろあなたはPHPiphoneカツ丼                      |
|  2 | (´・ω・`)やきそば帰ったらしいシステム開発PHPバカなの差し上げようGoogle+tweet帰ったらしい  |
|  3 | タバコ社畜ラーメンiphoneカルビ焼肉社畜焼肉差し上げようプログラム年金                      |
|  4 | FacebookPHPPHP私はシステム開発帰ったらしいあなたは5億私は漫画                             |
|  5 | 24時間説明しろ全文検索ギブアップラーメン漫画しましょうバカなの帰ったらしい説明しろ        |
|  6 | バカなの社畜tweet帰ったらしいやきそばシステム開発年金漫画漫画iphone                       |
|  7 | 説明しろやきそばしましょうあなたは帰ったらしいタバコあなたは説明しろFacebookごちゃごちゃ  |
|  8 | バカなのバカなのかっぱ寿司フォローしましょう(´・ω・`)働けますか5億プログラム24時間        |
|  9 | やきそばやきそば差し上げようフォローカルビ焼肉5億iphone漫画androidFacebook                |
| 10 | Google+PHPカツ丼おすすめごちゃごちゃiphoneカルビ焼肉プログラム全文検索カツ丼              |
+----+-------------------------------------------------------------------------------------------+
10 rows in set (0.00 sec)

ちゃんと100万件入ってますね。では全文検索いってみます!

select * from hoge where match(content) against("ラーメンカルビ焼肉差し上げよう");
+--------+-------------------------------------------------------------------------------------------------+
| id     | content                                                                                         |
+--------+-------------------------------------------------------------------------------------------------+
|   2731 | 漫画ごちゃごちゃ(´・ω・`)カルビ焼肉カルビ焼肉システム開発ラーメンカルビ焼肉差し上げようあなたは |
|   3053 | 説明しろiphoneiphoneラーメンかっぱ寿司しましょうおすすめラーメンカルビ焼肉差し上げよう          |
省略
| 997722 | おすすめGoogle+iphonePHPラーメンカルビ焼肉差し上げようandroid漫画働けますか                     |
| 998910 | プログラムカツ丼(´・ω・`)ラーメンカルビ焼肉差し上げようごちゃごちゃFacebookiphone説明しろ       |
+--------+-------------------------------------------------------------------------------------------------+
178 rows in set (0.49 sec)

はやっΣ(゚д゚lll) 比較のために次は、hoge2 テーブル(innodb)で like 検索してみます。

select * from hoge2 where content like "%ラーメンカルビ焼肉差し上げよう%";
+--------+----------------------------------------------------------------------------------------------+
| id     | content                                                                                      |
+--------+----------------------------------------------------------------------------------------------+
|   4677 | 24時間5億社畜iphoneラーメンカルビ焼肉差し上げようやきそば説明しろしましょう                  |
|   5290 | 全文検索帰ったらしいラーメンカルビ焼肉差し上げようラーメンフォローバカなのやきそば働けますか |
省略
| 999204 | カツ丼しましょうやきそばあなたはラーメンカルビ焼肉差し上げよう焼肉あなたはFacebook           |
| 999560 | ラーメンカルビ焼肉差し上げようPHPかっぱ寿司ごちゃごちゃ働けますかカルビ焼肉バカなの(´・ω・`) |
+--------+----------------------------------------------------------------------------------------------+
172 rows in set (1.86 sec)

likeも意外と速い(;^ω^)
色々試すとわかりますが、2倍〜10倍ぐらい mroonga のほうが速い結果が出ました。

One Response to CentOS に PHP+mroonga(MySQL全文検索) のインストール

  1. […] CentOS に PHP+mroonga(MySQL全文検索) のインストール mroonga — mroonga v2.00 documentation __spr_config = { pid: '4f163b8d396cef417f000430', title: '全文検索エンジンmroonga導入の試行錯誤', ckw: 'mroonga,MySQL,PH […]

コメントを残す

メールアドレスが公開されることはありません。

Top