LoginSignup
0
0

More than 3 years have passed since last update.

MySQLでマルチバイト含む文字列カラム検索(like,with ngram,mroonga)

Last updated at Posted at 2019-08-30

う゛ぁーじょん

CentOS7
MySQL 8.0.17
Mroonga 9.05
MeCab 0.996

やりたいこと

そこそこ件数が膨らむ算段のテーブルのVARCHAR(128)カラムに対し、曖昧な検索をかける。
その際、欲しい結果としては部分一致(LIKE '%検索ワード%')。

とりあえず

CREATE TABLE test (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  name VARCHAR(128) NOT NULL UNIQUE,
  PRIMARY KEY (id),
  FULLTEXT KEY ftk_test_name (name) COMMENT 'tokenizer "TokenMecab"'
) ENGINE=mroonga DEFAULT CHARSET=utf8mb4;

このテーブルにa-zまでの英小文字のみで構成される、5文字のstringを100万件放り込む。

没案

  FULLTEXT KEY ftk_test_name (name) WITH PARSER NGRAM'

mysql 5.7からデフォルトで全文検索できるようになってると聞いたので試したが、
検索結果が大きくなるようなクエリだと何故かempty setが返る。調べたところ、

結果セットがテーブル全体の50%を超えたらあかんでみたいなこと書いてある。
IN BOOLEAN MODE つけても結果に変化はなかったので、結果セットが小さくなるように頑張れよって意味か…?

何にせよ、使いづらそうなのでmroonga導入。

like結果

SELECT COUNT(*) FROM test where name LIKE '%abc%';
+----------+
| count(*) |
+----------+
|      207 |
+----------+
1 row in set (1.32 sec)

やはりlikeだとちょい遅い。最初から件数がデカくなると分かっているテーブルに対して持ち出したくない。

MATCH AGAINST結果

SELECT COUNT(*) FROM test WHERE MATCH(name) AGAINST('abc');
+----------+
| count(*) |
+----------+
|       67 |
+----------+
1 row in set (0.11 sec)

SELECT COUNT(*) FROM test WHERE MATCH(name) AGAINST('abc' in boolean mode);
+----------+
| count(*) |
+----------+
|       67 |
+----------+
1 row in set (0.00 sec)

速いのはいいけど、これ前方一致検索結果だよ。 LIKE 'abc%' になっちまってる。
いや、困った。mroongaのドキュメント見る限り、特に何もせずとも普通は最初から部分一致検索に思うんだけど…
知ってる方いたらそっと教えてください

追記

FULLTEXT KEY ftk_test_name (name) COMMENT 'tokenizer "TokenBigramSplitSymbolAlphaDigit"'

にしたらあっさり解決しました。アホすぎ。
※今回のデータ要件はマルチバイト・英数字全部入る可能性があるのでDigitにしてます

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0