HOPES

MariaDBで高速な日本語全文検索機能を実現するMroongaのインストールと設定

MariaDBで高速な日本語全文検索機能を実現するMroongaのインストールと設定

MariaDBで高速な日本語全文検索機能を実現するMroongaのインストールと設定、形態素解析エンジンMeCabの利用についてまとめています。

Mroongaについて

Mroongaは、MySQLのプラグインとして動作するたMySQLのストレージエンジンで、比較的容易にデータベースに組み込むことができ、いつも利用するMariaDB等の環境で、高速な日本語全文検索機能が利用できるようになります。

Mroongaは全文検索エンジンであるGroongaをベースとしたMySQLのストレージエンジンです。

1. Mroongaの特徴 — Mroonga v12.06 documentation


Mroongaのインストール

それでは、インストールを行います。

今回の環境

ここでのサーバは、AlmaLinux8です。

# cat /etc/redhat-release
AlmaLinux release 8.6 (Sky Tiger)

今回は、AlmaLinux 8に、MariaDB 10.6のパッケージを利用して、インストールします。

AlmaLinux 8では、Mroonga 11.10からMariaDB提供のMariaDB 10.6パッケージを利用できます。

2.5. AlmaLinux — Mroonga v12.06 documentation

パッケージのインストール

公式のドキュメントに従って進めていきます。

MariaDB10.6のリポジトリを作成します。

# vi /etc/yum.repos.d/MariaDB.repo
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.6/centos8-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1

groongaのリポジトリをインストールします。

# dnf -y install https://packages.groonga.org/almalinux/8/groonga-release-latest.noarch.rpm
インストール済み:
  groonga-release-2021.10.30-1.noarch                                                                                                       

完了しました!

ここでは、トークナイザーに形態素解析エンジンのMecabを利用するよう設定するので、Mecabやその他の必要となるパッケージをインストールします。

# dnf install --enablerepo=epel msgpack xxhash-libs re2 mecab mecab-ipadic 
# dnf install --enablerepo=powertools gflags glog

MeCabのインストールを確認しておきます。

# mecab -D
filename:	/usr/lib64/mecab/dic/ipadic/sys.dic
version:	102
charset:	utf8
type:	0
size:	392126
left size:	1316
right size:	1316

「mariadb」と「mysql」のモジュールを無効化します。

# dnf module -y disable mariadb
# dnf module -y disable mysql

MariaDB10.6をインストールします。

# dnf install -y --enablerepo=powertools mariadb-server
インストール済み:
  MariaDB-client-10.6.9-1.el8.x86_64         MariaDB-common-10.6.9-1.el8.x86_64          MariaDB-server-10.6.9-1.el8.x86_64                   
  MariaDB-shared-10.6.9-1.el8.x86_64         boost-program-options-1.66.0-10.el8.x86_64  galera-4-26.4.12-1.el8.x86_64                        
  libpmem-1.6.1-1.el8.x86_64                 lsof-4.93.2-1.el8.x86_64                    perl-DBI-1.641-4.module_el8.6.0+2823+173faa7e.x86_64 
  perl-Math-BigInt-1:1.9998.11-7.el8.noarch  perl-Math-Complex-1.59-421.el8.noarch       socat-1.7.4.1-1.el8.x86_64                           

完了しました!

MariaDBを起動します。

# systemctl start mariadb

mroongaパッケージをインストールします。

# dnf install -y --enablerepo=powertools mariadb-10.6-mroonga
ダウングレード済み:
  MariaDB-client-10.6.8-1.el8.x86_64                                    MariaDB-server-10.6.8-1.el8.x86_64                                   
インストール済み:
  arrow8-libs-8.0.0-1.el8.x86_64         gflags-2.1.2-6.el8.x86_64                       gflags-devel-2.1.2-6.el8.x86_64                    
  glog-0.3.5-3.el8.x86_64                groonga-libs-12.0.6-1.el8.x86_64                groonga-normalizer-mysql-1.1.8-1.el8.x86_64        
  lz4-1.8.3-3.el8_4.x86_64               mariadb-10.6-mroonga-12.06-1.el8.x86_64        

完了しました!

管理ユーザーのパスワードを設定しておきます。

# mysqladmin -u root password 'setting_password'
# mysqladmin -p -u root -h localhost  password 'setting_password'
Enter password: 

トークナイザーとして、形態素解析エンジンのMecabを利用できるようにパッケージをインストールします。

# dnf install -y --enablerepo=epel groonga-tokenizer-mecab
インストール済み:
  groonga-tokenizer-mecab-12.0.6-1.el8.x86_64                                                                                                 

完了しました!

今回の環境では、mroongaパッケージをインストールした際に、「MariaDB-server」と「MariaDB-client」がダウングレードされています。このまま、「dnf updade」等をかけるとエラーとなってしまうので、mroongaパッケージの対応を確認して、場合によっては、これらのパッケージを除外するよう「dnf update –exclude=MariaDB-server,MariaDB-client」とする必要があります。

インストールチェック

正常にインストールが完了していることを確認します。

Mroongaを使う前にMroongaのインストールチェックをした方がよいです。もし、Mroongaのインストールに失敗していると、このチュートリアルででてくるSQLが失敗してしまいます。

4.1. インストールチェック — Mroonga v12.06 documentation


ストレージエンジンのリストを確認して、Mroongaがリストにあることを確認します。

# mysql -u root -p
MariaDB [(none)]> SHOW ENGINES;
+--------------------+---------+-------------------------------------------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                                                         | Transactions | XA   | Savepoints |
+--------------------+---------+-------------------------------------------------------------------------------------------------+--------------+------+------------+
| CSV                | YES     | Stores tables as CSV files                                                                      | NO           | NO   | NO         |
| MRG_MyISAM         | YES     | Collection of identical MyISAM tables                                                           | NO           | NO   | NO         |
| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables                                       | NO           | NO   | NO         |
| Aria               | YES     | Crash-safe tables with MyISAM heritage. Used for internal temporary tables and privilege tables | NO           | NO   | NO         |
| MyISAM             | YES     | Non-transactional engine with good performance and small data footprint                         | NO           | NO   | NO         |
| SEQUENCE           | YES     | Generated tables filled with sequential values                                                  | YES          | NO   | YES        |
| Mroonga            | DEFAULT | CJK-ready fulltext search, column store                                                         | NO           | NO   | NO         |
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                                                              | NO           | NO   | NO         |
| InnoDB             | YES     | Supports transactions, row-level locking, foreign keys and encryption for tables                | YES          | YES  | YES        |
+--------------------+---------+-------------------------------------------------------------------------------------------------+--------------+------+------------+
9 rows in set (0.000 sec)

MariaDBとMroongaの設定

MariaDBとMroongaの初期の設定を行います。

自動起動の設定

デフォルトでは、自動起動の設定が無効になっているので、再起動等を行っても、MariaDBが自動起動するよう設定します。

# systemctl is-enabled mariadb
disabled
# systemctl enable mariadb
Created symlink /etc/systemd/system/multi-user.target.wants/mariadb.service → /usr/lib/systemd/system/mariadb.service.

設定ファイルによる設定

設定ファイルを編集して、環境に応じてMariaDBの設定行います。

Mroongaの設定については、デフォルトのストレージエンジンとして、「Mroonga」、また、トークナイザーは、「TokenMecab」が選択されるように設定します。

character-set-server=utf8mb4
max_connections = 1000
thread_cache_size = 1000
skip-name-resolve
slow_query_log = 1
long_query_time = 1
read_buffer_size = 4G

# InnoDB
innodb_buffer_pool_size = 16G
innodb_log_file_size = 4G
innodb_flush_method=O_DIRECT

# Mroonga
default-storage-engine=Mroonga
mroonga_default_tokenizer=TokenMecab

また、 my.cnf またはSQL内で mroonga_default_tokenizer 変数を指定することでも指定できます。 my.cnf で指定するとMySQLを再起動しても値は変更されたままですが、反映させるために再起動しなければいけません。一方、SQLで指定した場合はすぐに設定が反映されますが、MySQLが再起動すると設定は失われます。

4.3. ストレージモード — Mroonga v12.06 documentation


全文検索の使い方

動作確認を兼ねて、全文検索の使い方を試します。

全文検索の基本利用

テスト用のデータベースを作成して利用します。

# mysql -u root -p
CREATE DATABASE `search_test`;
Query OK, 1 row affected (0.000 sec)

MariaDB [(none)]> use search_test
Database changed
MariaDB [search_test]> 

ドキュメントのチュートリアルに従って進めます。

テーブルを作成してデータを挿入します。

MariaDB [search_test]> CREATE TABLE `diaries` (`id` INT PRIMARY KEY AUTO_INCREMENT, `content` VARCHAR(255), FULLTEXT INDEX (content)) ENGINE = Mroonga;
Query OK, 0 rows affected, 1 warning (0.072 sec)

MariaDB [search_test]> INSERT INTO `diaries` (content) VALUES ("It'll be fine tomorrow."), ("It'll rain tomorrow");
Query OK, 2 rows affected (0.022 sec)
Records: 2  Duplicates: 0  Warnings: 0

検索すると、データが取得できることが確認できます。

MariaDB [search_test]> SELECT * FROM diaries WHERE MATCH(content) AGAINST("+fine" IN BOOLEAN MODE);
+----+-------------------------+
| id | content                 |
+----+-------------------------+
|  1 | It'll be fine tomorrow. |
+----+-------------------------+
1 row in set (0.067 sec)

検索スコアの利用

検索キーワードに一致する数が多い順に表示するため等に使う検索スコアの利用を確認します。

全文検索を行う際、指定したキーワードにより内容が一致するレコードを上位に表示したいというような場合があります。そうしたケースでは検索スコアを利用します。

4.3. ストレージモード — Mroonga v12.06 documentation

追加でデータを挿入します。

MariaDB [search_test]> INSERT INTO `diaries` (content) VALUES("It's fine today. It'll be fine tomorrow as well."), ("It's fine today. But it'll rain tomorrow.");
Query OK, 2 rows affected (0.003 sec)
Records: 2  Duplicates: 0  Warnings: 0

検索スコアを利用して、データを取得します。検索スコアを利用してソート出来ていることが確認できます。

MariaDB [search_test]> SELECT *, MATCH (content) AGAINST ("+fine" IN BOOLEAN MODE) AS score FROM diaries WHERE MATCH (content) AGAINST ("+fine" IN BOOLEAN MODE) ORDER BY MATCH (content) AGAINST ("+fine" IN BOOLEAN MODE) DESC;
+----+--------------------------------------------------+-------+
| id | content                                          | score |
+----+--------------------------------------------------+-------+
|  3 | It's fine today. It'll be fine tomorrow as well. |     2 |
|  1 | It'll be fine tomorrow.                          |     1 |
|  4 | It's fine today. But it'll rain tomorrow.        |     1 |
+----+--------------------------------------------------+-------+
3 rows in set (0.002 sec)

形態素解析エンジンMeCabの利用

ここでは、デフォルトのトークナイザーにMeCabが利用されるよう設定していますが、正常に動作していることを確認します。

トークナイザーにMeCabが利用できるようになっていることを確認します。

MariaDB [search_test]> SELECT mroonga_command("tokenize TokenMecab '東京都'");
+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| mroonga_command("tokenize TokenMecab '東京都'")                                                                                                                  |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| [{"value":"東京","position":0,"force_prefix":false,"force_prefix_search":false},{"value":"都","position":1,"force_prefix":false,"force_prefix_search":false}]    |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.001 sec)

トークナイザーに「TokenBigram」を指定した「address1」テーブルとデフォルトで「TokenMecab」が指定される2つのテーブルを作成します。

MariaDB [search_test]> CREATE TABLE `address1` (`id` INT NOT NULL AUTO_INCREMENT , `address` VARCHAR(255) NOT NULL , PRIMARY KEY (`id`), FULLTEXT `address` (`address`) COMMENT 'tokenizer "TokenBigram"') ENGINE = Mroonga;
Query OK, 0 rows affected (0.096 sec)

MariaDB [search_test]> CREATE TABLE `address2` (`id` INT NOT NULL AUTO_INCREMENT , `address` VARCHAR(255) NOT NULL , PRIMARY KEY (`id`), FULLTEXT `address` (`address`)) ENGINE = Mroonga;
Query OK, 0 rows affected, 1 warning (0.024 sec)

それぞれ、データを挿入します。

MariaDB [search_test]> INSERT INTO `address1` (`id`, `address`) VALUES (NULL, '北海道札幌市中央区北3条西6-1'), (NULL, '東京都新宿区西新宿2-8-1'), (NULL, '京都府京都市上京区下立売通新町西入薮ノ内町'), (NULL, '鹿児島県鹿児島市鴨池新町10-1');
Query OK, 4 rows affected (0.018 sec)
Records: 4  Duplicates: 0  Warnings: 0

MariaDB [search_test]> INSERT INTO `address2` (`id`, `address`) VALUES (NULL, '北海道札幌市中央区北3条西6-1'), (NULL, '東京都新宿区西新宿2-8-1'), (NULL, '京都府京都市上京区下立売通新町西入薮ノ内町'), (NULL, '鹿児島県鹿児島市鴨池新町10-1');
Query OK, 4 rows affected (0.013 sec)
Records: 4  Duplicates: 0  Warnings: 0

それぞれのテーブルで、「京都」をキーワードに検索します。「address1」では、東京都も検索にヒットしますが、「address2」では、MeCabによって、分かち書きされているので、京都だけがヒットしていることが確認できます。

MariaDB [search_test]> SELECT * FROM `address1` WHERE MATCH(`address`) AGAINST("+京都" IN BOOLEAN MODE);
+----+-----------------------------------------------------------------+
| id | address                                                         |
+----+-----------------------------------------------------------------+
|  3 | 京都府京都市上京区下立売通新町西入薮ノ内町                      |
|  2 | 東京都新宿区西新宿2-8-1                                         |
+----+-----------------------------------------------------------------+
2 rows in set (0.091 sec)

MariaDB [search_test]> SELECT * FROM `address2` WHERE MATCH(`address`) AGAINST("+京都" IN BOOLEAN MODE);
+----+-----------------------------------------------------------------+
| id | address                                                         |
+----+-----------------------------------------------------------------+
|  3 | 京都府京都市上京区下立売通新町西入薮ノ内町                      |
+----+-----------------------------------------------------------------+
1 row in set (0.049 sec)

インストールと動作の確認もできたので、これで完了です。

2022年08月20日に投稿されました。

2022年09月27日に更新されました。