Mroonga(MySQL)やLIKE・FULLTEXTインデックスの全文検索の性能を比較してみた
はじめに
こんにちは、SHIFT の開発部門に所属している Katayama です。
性能比較のためにdocker-composeでMroonga(MySQL)のセットアップをしたら結構時間がかかった話では性能比較のために Mroonga のセットアップをやってみた所、思ったよりも時間がかかってしまった事を取り上げた。
今回はその記事のまとめで触れていた Mroonga を用いた場合の全文検索の性能について、実際に InnoDB との速度を比較してみたのでそれについてみていきたいと思います。
※「おまけ」では LIKE による検索での速度計測してみたり、転置インデックス・完全転置インデックスでの速度の違いに関しても触れています。
本題の前に 日本語全文検索の速度向上のために取れるアプローチは?
実際に全文検索の速度の比較を見ていく前に、全文検索の速度を向上させるためにどのような選択肢があるか?を考えてみると、以下のような選択肢が少なくともあるだろう(以下は DB を MySQL と想定して書き出してるが、MySQL 以外の製品を利用して高速化できる場合もあるのでそれも含めて書き出している)。
・MySQL の InnoDB で FULLTEXT インデックスを張る
プレーンな MySQL でやる場合のアプローチ。ただし、「おまけ」の「InnoDB は転置インデックスなので注意」で取り上げたように FULLTEXT インデックスは転置インデックスなのでパフォーマンスが極端に悪くなるパターンがあるので注意が必要。
詳細は公式を参照。
・Mroonga を利用する
今回実際にこの後見ていくが、Mroonga は MySQL のプラグインであり、ストレージエンジンとして指定して利用するもの。
詳細は公式を参照。
・Elasticsearch
検索エンジンと言えば Elasticsearch、と言われるくらいデファクトなので言わずもがなかもしれないが、Elasticsearch を利用するというのも 1 つ。
詳細は公式を参照
・HyperEstraier を利用する
全文検索システムであるが、公式サイトは Copyright (C) 2004-2007 となっているので現在どうなっているかは不明。
詳細は公式を参照
上記で見たように全文検索の速度向上させる方法にはいくつかのアプローチがあるが、その中で今回は Mroonga を利用した速度向上の体感(InnoDBと比べた性能の比較)をしてみたいと思う。
実際に速度を比較してみる
実際に以下のようなテーブルで全文検索の速度を比較してみる。
CREATE TABLE `full_text_search_innodb` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`text` varchar(255) NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
FULLTEXT KEY `text_idx` (`text`) /*!50100 WITH PARSER `ngram` */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `full_text_search_mroonga` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`text` varchar(255) NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
FULLTEXT KEY `text_idx` (`text`) /*!50100 WITH PARSER `ngram` */
) ENGINE=Mroonga DEFAULT CHARSET=utf8mb4;
※以下の SQL で出てくる"IN BOOLEAN MODE"の詳細については12.10.2 Boolean Full-Text Searchesを参照。厳密に部分一致で検索する場合には"IN BOOLEAN MODE"で検索を行う。
※今回は"ngram_token_size=2"としたので2文字ずつの文字分割で FULLTEXT インデックスが作成される。という事は必然的に 1 文字での検索はできなくなるが、今回の検証では問題にならないので気にしない("ngram_token_size"についてはConfiguring ngram Token Sizeを参照)。
mysql> SHOW VARIABLES LIKE 'ngram_token_size';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| ngram_token_size | 2 |
+------------------+-------+
1 row in set (0.01 sec)
InnnoDB
mysql> SELECT COUNT(*) FROM `full_text_search_innodb` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE);
+----------+
| COUNT(*) |
+----------+
| 100001 |
+----------+
1 row in set (0.60 sec)
...
mysql> SELECT EVENT_ID, TRUNCATE(TIMER_WAIT/1000000000000,6) as Duration, SQL_TEXT FROM performance_schema.events_statements_history_long WHERE SQL_TEXT like '%猫で%' AND SQL_TEXT like '%full_text_search_innodb%';
+----------+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| EVENT_ID | Duration | SQL_TEXT |
+----------+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 73 | 0.729086 | SELECT COUNT(*) FROM `full_text_search_innodb` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
| 86 | 0.670203 | SELECT COUNT(*) FROM `full_text_search_innodb` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
| 99 | 0.668161 | SELECT COUNT(*) FROM `full_text_search_innodb` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
| 112 | 0.664694 | SELECT COUNT(*) FROM `full_text_search_innodb` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
| 125 | 0.662405 | SELECT COUNT(*) FROM `full_text_search_innodb` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
+----------+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Mroonga
mysql> SELECT COUNT(*) FROM `full_text_search_mroonga` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE);
+----------+
| COUNT(*) |
+----------+
| 100001 |
+----------+
1 row in set (0.00 sec)
...
mysql> SELECT EVENT_ID, TRUNCATE(TIMER_WAIT/1000000000000,6) as Duration, SQL_TEXT FROM performance_schema.events_statements_history_long WHERE SQL_TEXT like '%猫で%' AND SQL_TEXT like '%full_text_search_mroonga%';
+----------+----------+-------------------------------------------------------------------------------------------------------+
| EVENT_ID | Duration | SQL_TEXT |
+----------+----------+-------------------------------------------------------------------------------------------------------+
| 219 | 0.015805 | SELECT COUNT(*) FROM `full_text_search_mroonga` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
| 232 | 0.014677 | SELECT COUNT(*) FROM `full_text_search_mroonga` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
| 245 | 0.014390 | SELECT COUNT(*) FROM `full_text_search_mroonga` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
| 258 | 0.016135 | SELECT COUNT(*) FROM `full_text_search_mroonga` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
| 271 | 0.016368 | SELECT COUNT(*) FROM `full_text_search_mroonga` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
+----------+----------+-------------------------------------------------------------------------------------------------------+
※上記は100万行に対する検索だが、1000万行あるとどうなるかもやってみると以下のような結果になった。平均で約0.17秒で100万行の時の速度に比べ10倍遅くなっている(LIKE vs FULLTEXT インデックス vs Mroongaも検証してみたが、それについては「おまけ」の「1000 万行のデータに対する検索 LIKE vs FULLTEXT インデックス vs Mroonga」を参照)。
mysql> SELECT EVENT_ID, TRUNCATE(TIMER_WAIT/1000000000000,6) as Duration, SQL_TEXT FROM performance_schema.events_statements_history_long WHERE SQL_TEXT like '%full_text_search_mroonga%';
+----------+----------+-------------------------------------------------------------------------------------------------------+
| EVENT_ID | Duration | SQL_TEXT |
+----------+----------+-------------------------------------------------------------------------------------------------------+
| 208 | 0.323640 | SELECT COUNT(*) FROM `full_text_search_mroonga` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
| 221 | 0.145316 | SELECT COUNT(*) FROM `full_text_search_mroonga` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
| 234 | 0.147189 | SELECT COUNT(*) FROM `full_text_search_mroonga` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
| 247 | 0.146746 | SELECT COUNT(*) FROM `full_text_search_mroonga` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
| 260 | 0.147747 | SELECT COUNT(*) FROM `full_text_search_mroonga` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
+----------+----------+-------------------------------------------------------------------------------------------------------+
5 rows in set (0.00 sec)
速度の比較結果
InnoDB と Mroonga では以下のように大きな差がある事が確認できた(約 45 倍の差がある)。
※上記の速度計測にあたっては、MySQLのクエリーキャッシュが使われていないことは確認済み("Qcache_hits "が0になっている)。
mysql> SHOW STATUS LIKE 'Qcache%';
+-------------------------+---------+
| Variable_name | Value |
+-------------------------+---------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 1031832 |
| Qcache_hits | 0 |
| Qcache_inserts | 0 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 35 |
| Qcache_queries_in_cache | 0 |
| Qcache_total_blocks | 1 |
+-------------------------+---------+
まとめとして
今回は Mroonga を利用して全文検索をやってみる事で、InnoDB の FULLTEXT インデックスのみとの速度の差を見てみた。速度としては Mroonga を利用した時の方が圧倒的に早く、性能が要求される場面ではどの技術を選定するのか?が重要になる事も体感できた。
※InnoDB と Mroonga の全文検索の差が顕著になるのは"ngram_token_size"を超えた単語数で検索を行う時で、それには転置インデックス・完全転置インデックスの話が関係してくる。詳細は「おまけ」の「InnoDB は転置インデックスなので注意」で実際に速度比較をしてみたのでそちらを参照。
参考文献
おまけ
LIKE による検索のパフォーマンスについて
データ量が少ない場合には LIKE による検索もよく行われると思うが、今回のような 100 万行のデータがある場合にはどうなるか?を検証してみる。結果としては以下の通り。平均で約 0.569 秒で、上記の FULLTEXT インデックスを張った時よりも若干早いという結果になった(あくまで筆者の環境での話)。
※ちなみに、上記の LIKE の速度で実用に耐えられるか?と考えてみると秒間のアクセス数の要件によっては全く耐えられないという事もあるので注意は必要だろう。
mysql> SELECT EVENT_ID, TRUNCATE(TIMER_WAIT/1000000000000,6) as Duration, SQL_TEXT FROM performance_schema.events_statements_history_long WHERE SQL_TEXT like '%SELECT COUNT(*) FROM `full_text_search` WHERE `text` LIKE%';
+----------+----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| EVENT_ID | Duration | SQL_TEXT |
+----------+----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 467 | 0.603078 | SELECT COUNT(*) FROM `full_text_search` WHERE `text` LIKE '%猫で%' |
| 483 | 0.567624 | SELECT COUNT(*) FROM `full_text_search` WHERE `text` LIKE '%猫で%' |
| 499 | 0.557476 | SELECT COUNT(*) FROM `full_text_search` WHERE `text` LIKE '%猫で%' |
| 515 | 0.567569 | SELECT COUNT(*) FROM `full_text_search` WHERE `text` LIKE '%猫で%' |
| 531 | 0.555271 | SELECT COUNT(*) FROM `full_text_search` WHERE `text` LIKE '%猫で%' |
+----------+----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
※ちなみに、LIKE ではインデックスは前方一致を除き無視されるので、LIKE による検索を行ったテーブル"full_text_search"(以下の SQL を参照)にインデックスが張られていてもパフォーマンス検証には問題ならない(インデックスの有無で LIKE の実行結果は変わらないという事)。
CREATE TABLE `full_text_search` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`text` varchar(255) NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
KEY `text_idx` (`text`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
※前方一致の LIKE だとどうなるか?だが、以下の通り。部分一致(インデックスは効かない)よりも高速に検索できている事が分かる(以下の時間は検索にヒットするものは同じものになるように検索を実行した際の時間)。
mysql> SELECT EVENT_ID, TRUNCATE(TIMER_WAIT/1000000000000,6) as Duration, SQL_TEXT FROM performance_schema.events_statements_history_long WHERE SQL_TEXT like '%吾輩は猫%';
+----------+----------+----------------------------------------------------------------------------------------------+
| EVENT_ID | Duration | SQL_TEXT
+----------+----------+----------------------------------------------------------------------------------------------+
| 823 | 0.051097 | SELECT COUNT(*) FROM `full_text_search` WHERE `text` LIKE '吾輩は猫%' |
| 839 | 0.051095 | SELECT COUNT(*) FROM `full_text_search` WHERE `text` LIKE '吾輩は猫%' |
| 855 | 0.050013 | SELECT COUNT(*) FROM `full_text_search` WHERE `text` LIKE '吾輩は猫%' |
| 871 | 0.051844 | SELECT COUNT(*) FROM `full_text_search` WHERE `text` LIKE '吾輩は猫%' |
| 887 | 0.054329 | SELECT COUNT(*) FROM `full_text_search` WHERE `text` LIKE '吾輩は猫%' |
+----------+----------+----------------------------------------------------------------------------------------------+
...
mysql> SELECT EVENT_ID, TRUNCATE(TIMER_WAIT/1000000000000,6) as Duration, SQL_TEXT FROM performance_schema.events_statements_history_long WHERE SQL_TEXT like '%COUNT(*) FROM `full_text_search`%' AND SQL_TEXT like '%吾輩は猫%';
+----------+----------+--------------------------------------------------------------------------------------------------------------+
| EVENT_ID | Duration | SQL_TEXT |
+----------+----------+--------------------------------------------------------------------------------------------------------------+
| 1127 | 0.604210 | SELECT COUNT(*) FROM `full_text_search` WHERE `text` LIKE '%吾輩は猫%' |
| 1143 | 0.572866 | SELECT COUNT(*) FROM `full_text_search` WHERE `text` LIKE '%吾輩は猫%' |
| 1159 | 0.596613 | SELECT COUNT(*) FROM `full_text_search` WHERE `text` LIKE '%吾輩は猫%' |
| 1175 | 0.585640 | SELECT COUNT(*) FROM `full_text_search` WHERE `text` LIKE '%吾輩は猫%' |
| 1191 | 0.579653 | SELECT COUNT(*) FROM `full_text_search` WHERE `text` LIKE '%吾輩は猫%' |
+----------+----------+--------------------------------------------------------------------------------------------------------------+
14 rows in set (0.00 sec)
InnoDB は転置インデックスなので注意
公式にも書かれている通り、MySQL の InnoDB における FULLTEXT インデックスは転置インデックスの設計がされている。(転置インデックスの詳細についてはこの記事の範疇を超えるので扱わないが、)このため ngram と同じ文字数(今回だと 2 文字)であれば検索は早いが、それを超えると極端に速度が落ちる。これは転置インデックスが「ある単語が出てくる文章(レコード)を記憶する」インデックスで、文章の単語の並び順までは分からないため。
実際、テーブル総行数が約 100 万行あるテーブルで検索をかけてみると以下のように 1 分以上もかかってしまう・・・。そしてテーブルのデータ行数によっては、上記で見たように単に LIKE で検索を行った方が遥かに早く検索が終わる事も分かる。
mysql> SELECT EVENT_ID, TRUNCATE(TIMER_WAIT/1000000000000,6) as Duration, SQL_TEXT FROM performance_schema.events_statements_history_long WHERE SQL_TEXT like '%full_text_search_innodb%' AND SQL_TEXT like '%猫であ%';
+----------+------------+--------------------------------------------------------------------------------------------------------------------------+
| EVENT_ID | Duration | SQL_TEXT |
+----------+------------+--------------------------------------------------------------------------------------------------------------------------+
| 300 | 78.148857 | SELECT COUNT(*) FROM `full_text_search_innodb` WHERE MATCH (text) AGAINST ('猫であ' IN BOOLEAN MODE) |
| 313 | 70.506695 | SELECT COUNT(*) FROM `full_text_search_innodb` WHERE MATCH (text) AGAINST ('猫であ' IN BOOLEAN MODE) |
| 326 | 71.841219 | SELECT COUNT(*) FROM `full_text_search_innodb` WHERE MATCH (text) AGAINST ('猫であ' IN BOOLEAN MODE) |
| 1069 | 64.130336 | SELECT COUNT(*) FROM `full_text_search_innodb` WHERE MATCH (text) AGAINST ('猫であ' IN BOOLEAN MODE) |
| 1082 | 67.545795 | SELECT COUNT(*) FROM `full_text_search_innodb` WHERE MATCH (text) AGAINST ('猫であ' IN BOOLEAN MODE) |
+----------+------------+--------------------------------------------------------------------------------------------------------------------------+
...
mysql> SELECT EVENT_ID, TRUNCATE(TIMER_WAIT/1000000000000,6) as Duration, SQL_TEXT FROM performance_schema.events_statements_history_long WHERE SQL_TEXT like '%full_text_search_innodb%' AND SQL_TEXT like '%猫である%';
+----------+------------+------------------------------------------------------------------------------------------------------------+
| EVENT_ID | Duration | SQL_TEXT |
+----------+------------+------------------------------------------------------------------------------------------------------------+
| 972 | 207.264565 | SELECT COUNT(*) FROM `full_text_search_innodb` WHERE MATCH (text) AGAINST ('猫である' IN BOOLEAN MODE) |
| 985 | 194.980081 | SELECT COUNT(*) FROM `full_text_search_innodb` WHERE MATCH (text) AGAINST ('猫である' IN BOOLEAN MODE) |
| 998 | 200.471678 | SELECT COUNT(*) FROM `full_text_search_innodb` WHERE MATCH (text) AGAINST ('猫である' IN BOOLEAN MODE) |
| 1011 | 207.048842 | SELECT COUNT(*) FROM `full_text_search_innodb` WHERE MATCH (text) AGAINST ('猫である' IN BOOLEAN MODE) |
| 1024 | 191.172078 | SELECT COUNT(*) FROM `full_text_search_innodb` WHERE MATCH (text) AGAINST ('猫である' IN BOOLEAN MODE) |
+----------+------------+------------------------------------------------------------------------------------------------------------+
5 rows in set (0.29 sec)
同じ検索を Mroonga で行うと、Mroonga は完全転置インデックスなので文章の単語の並び順(その単語が文章のどの位置に出現するか)まで分かり、以下のように直に(約 0.04 秒で)検索結果が返ってくる(テーブル総行数は約 100 万行で同じ)。
mysql> SELECT EVENT_ID, TRUNCATE(TIMER_WAIT/1000000000000,6) as Duration, SQL_TEXT FROM performance_schema.events_statements_history_long WHERE SQL_TEXT like '%full_text_search_mroonga%' AND SQL_TEXT like '% である%';
+----------+----------+-----------------------------------------------------------------------------------------------------------------+
| EVENT_ID | Duration | SQL_TEXT |
+----------+----------+-----------------------------------------------------------------------------------------------------------------+
| 1313 | 0.051220 | SELECT COUNT(*) FROM full_text_search_mroonga WHERE MATCH (text) AGAINST ('猫である' IN BOOLEAN MODE) |
| 1326 | 0.047464 | SELECT COUNT(*) FROM full_text_search_mroonga WHERE MATCH (text) AGAINST ('猫である' IN BOOLEAN MODE) |
| 1339 | 0.046014 | SELECT COUNT(*) FROM full_text_search_mroonga WHERE MATCH (text) AGAINST ('猫である' IN BOOLEAN MODE) |
| 1352 | 0.045480 | SELECT COUNT(*) FROM full_text_search_mroonga WHERE MATCH (text) AGAINST ('猫である' IN BOOLEAN MODE) |
| 1365 | 0.045213 | SELECT COUNT(*) FROM full_text_search_mroonga WHERE MATCH (text) AGAINST ('猫である' IN BOOLEAN MODE) |
+----------+----------+-----------------------------------------------------------------------------------------------------------------+
8 rows in set (0.00 sec)
・参考:InnoDB のフレーズ検索はなぜ遅いのか(転置インデックスと完全転置インデックス)
1000 万行のデータに対する検索 LIKE vs FULLTEXT インデックス vs Mroonga
上記の「LIKE による検索のパフォーマンスについて」では、FULLTEXT インデックスを張っていたテーブルでの検索よりも LIKE での検索の方が早いという結果になっていた。1000 万行のデータに対する検索であれば、FULLTEXT インデックス> LIKE になるのでは?と思い、実際にやってみると(あくまでも筆者の環境では)以下のような結果になった(Mroonga でもやってみた結果も載せている)。
mysql> SELECT EVENT_ID, TRUNCATE(TIMER_WAIT/1000000000000,6) as Duration, SQL_TEXT FROM performance_schema.events_statements_history_long WHERE SQL_TEXT like '%full_text_search%';
+----------+-----------+----------------------------------------------------------------------+
| EVENT_ID | Duration | SQL_TEXT |
+----------+-----------+----------------------------------------------------------------------+
| 31 | 17.971542 | SELECT COUNT(*) FROM `full_text_search` WHERE `text` LIKE '%猫で%' |
| 47 | 12.725061 | SELECT COUNT(*) FROM `full_text_search` WHERE `text` LIKE '%猫で%' |
| 63 | 13.065076 | SELECT COUNT(*) FROM `full_text_search` WHERE `text` LIKE '%猫で%' |
| 79 | 11.562536 | SELECT COUNT(*) FROM `full_text_search` WHERE `text` LIKE '%猫で%' |
| 95 | 15.362384 | SELECT COUNT(*) FROM `full_text_search` WHERE `text` LIKE '%猫で%' |
+----------+-----------+----------------------------------------------------------------------+
5 rows in set (0.43 sec)
...
mysql> SELECT EVENT_ID, TRUNCATE(TIMER_WAIT/1000000000000,6) as Duration, SQL_TEXT FROM performance_schema.events_statements_history_long WHERE SQL_TEXT like '%full_text_search_innodb%';
+----------+----------+------------------------------------------------------------------------------------------------------+
| EVENT_ID | Duration | SQL_TEXT |
+----------+----------+------------------------------------------------------------------------------------------------------+
| 127 | 1.566913 | SELECT COUNT(*) FROM `full_text_search_innodb` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
| 140 | 1.311382 | SELECT COUNT(*) FROM `full_text_search_innodb` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
| 153 | 1.308611 | SELECT COUNT(*) FROM `full_text_search_innodb` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
| 166 | 1.318342 | SELECT COUNT(*) FROM `full_text_search_innodb` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
| 179 | 1.299907 | SELECT COUNT(*) FROM `full_text_search_innodb` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
+----------+----------+------------------------------------------------------------------------------------------------------+
5 rows in set (0.01 sec)
...
mysql> SELECT EVENT_ID, TRUNCATE(TIMER_WAIT/1000000000000,6) as Duration, SQL_TEXT FROM performance_schema.events_statements_history_long WHERE SQL_TEXT like '%full_text_search_mroonga%';
+----------+----------+-------------------------------------------------------------------------------------------------------+
| EVENT_ID | Duration | SQL_TEXT |
+----------+----------+-------------------------------------------------------------------------------------------------------+
| 208 | 0.323640 | SELECT COUNT(*) FROM `full_text_search_mroonga` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
| 221 | 0.145316 | SELECT COUNT(*) FROM `full_text_search_mroonga` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
| 234 | 0.147189 | SELECT COUNT(*) FROM `full_text_search_mroonga` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
| 247 | 0.146746 | SELECT COUNT(*) FROM `full_text_search_mroonga` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
| 260 | 0.147747 | SELECT COUNT(*) FROM `full_text_search_mroonga` WHERE MATCH (text) AGAINST ('猫で' IN BOOLEAN MODE) |
+----------+----------+-------------------------------------------------------------------------------------------------------+
5 rows in set (0.00 sec)
《この公式ブロガーの記事一覧》
__________________________________
お問合せはお気軽に
https://service.shiftinc.jp/contact/
SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/
SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/
SHIFTの導入事例
https://service.shiftinc.jp/case/
お役立ち資料はこちら
https://service.shiftinc.jp/resources/
SHIFTの採用情報はこちら
https://recruit.shiftinc.jp/career/