序文
- Innodbおよびmyisamストレージエンジンのみがフルテキストインデックスを使用できます(innodbはmysql5.6以降のフルテキストインデックスをサポートしています)
- Char、varchar、テキストタイプのフィールドは、フルテキストインデックス(フルテキストインデックスタイプ)を作成できます
- フルテキストインデックスはキーワードに基づいています。異なるキーワードを区別するには、単語のセグメンテーション(ストップワード)を使用する必要があります
- 英語の単語はスペースとカンマで区切られています。中国語の単語のセグメンテーションは不便です(文は異なるキーワードを区別する方法がわかりません)
- 組み込みの単語分割パーサーngramは、中国語、日本語、韓国語(文を固定数に分割するフレーズ)をサポートします
- 大量のデータをテーブルに書き込む場合、データを書き込んだ後にフルテキストインデックスを作成する方が高速です(インデックスを維持するオーバーヘッドを削減します)。
- 全文索引付けの原則の逆索引(データ構造)。これは通常、連想配列を使用して、単語と文書の場所との間のマッピングを補助表に格納します。
使用する
MATCH()…AGAINSTを使用して検索
match()は列が検索されることを意味し、反対は検索される文字列が
デフォルトの単語セグメンテーションを表示します(これらの単語を使用してさまざまなキーワードを区別します)。単語セグメンテーションをカスタマイズして、これらの単語を使用してさまざまなキーワードを区別することもできます。SELECT * FROM information_schema.INNODB_FT_DEFAULT_STOPWORD;
として
3種類の全文検索方法
自然言語検索
デフォルトの方法であるMATCH AGAINSTを介して特定の文字列を渡して確認します。
ブール検索
取得した文字列に演算子を追加します。たとえば、「+」は含める必要がある、「-」は含まない、「*」はワイルドカードを意味します。渡された文字列が小さいか、ストップワードに含まれていても、フィルターされません
クエリ拡張検索
検索文字列は自然言語検索を実行するために使用され、次に検索によって返された最も関連性の高い行の単語が検索文字列に追加され、検索が再度実行され、クエリは2番目の検索から行を返します
関連パラメーター
関連パラメーターを構成する
innodb_ft_min_token_sizeのデフォルトは3で、キーワードとして3文字以上であることを示します。値を大きくすると、フルテキストインデックスのサイズを小さくできます
innodb_ft_max_token_sizeのデフォルトは84で、最大84文字をキーワードとして使用できることを意味します。この値を制限すると、フルテキストインデックスのサイズを小さくできます
ngram_token_sizeのデフォルトは2です。これは、組み込みトークナイザーのキーワードとして2文字が使用されることを意味します。たとえば、「abcd」のフルテキストインデックスを作成するには、キーワードは「ab」、「bc」、「cd」です。
ngramワードセグメンテーションパーサーを使用する場合、innodb_ft_min_token_sizeおよびinnodb_ft_max_token_sizeは無効です。
これら3つのパラメータは動的に変更できないことに注意してください。これらのパラメータを変更した場合、MySQLサービスを再起動してフルテキストインデックスを再確立する必要があります
全文索引を使用してinnodbエンジンをテストする
準備ができて
1.目標
- 記事に特定のキーワードが含まれているかどうかを問い合わせます。一連の記事が特定のキーワードに表示される回数
- 記事のタイトルにキーワードが含まれているかどうかを確認する
2.次のパラメーターを設定して、ディスクIOの負荷を軽減します。
SET GLOBAL sync_binlog=100;
SET GLOBAL innodb_flush_log_at_trx_commit=2;
3. 1kwデータをインポートして全文索引をテストします
データソースのオンライン検索
https://pan.baidu.com/s/1aaB1R3bkBGZRMEx0o6T61w抽出コード:60l7
4.記事テーブルの構造
myloaderマルチスレッドインポートテストデータを使用する
-- 先把测试数据进行解压
tar -zxf mydumper_dump_article.tar.gz
time myloader -u $user -p $passwd -S $socket -t 32 -d /datas/dump_article -v 3
5.データのインポート後、合計データ量と、データファイルとインデックスファイルのサイズ
SELECT COUNT(*) FROM `article`;
+----------+
| COUNT(*) |
+----------+
| 10000000 |
+----------+
1 row in set (7.85 sec)
SELECT table_name, CONCAT(FORMAT(SUM(data_length) / 1024 / 1024,2),'M') AS dbdata_size, CONCAT(FORMAT(SUM(index_length) / 1024 / 1024,2),'M') AS dbindex_size, CONCAT(FORMAT(SUM(data_length + index_length) / 1024 / 1024 / 1024,2),'G') AS `db_size(G)`, AVG_ROW_LENGTH,table_rows,update_time FROM information_schema.tables WHERE table_schema = DATABASE() and table_name='article';
+------------+-------------+--------------+------------+----------------+------------+---------------------+
| table_name | dbdata_size | dbindex_size | db_size(G) | AVG_ROW_LENGTH | table_rows | update_time |
+------------+-------------+--------------+------------+----------------+------------+---------------------+
| article | 3,710.00M | 1,003.00M | 4.60G | 414 | 9388739 | 2019-07-05 15:31:37 |
+------------+-------------+--------------+------------+----------------+------------+---------------------+
デフォルトの方法で全文索引を作成する
1.テーブルにはすでにキーワードフィールド(記事の内容の簡単な説明)があり、「、」をトークナイザーとして使用しています
2.全文索引を作成しないときにキーワードを検索する
全表スキャンが必要
3.キーワードフィールドにフルテキストインデックスを作成します(単語のセグメンテーションとして)
my.cnf構成ファイルでinnodb_ft_min_token_sizeを設定し、MySQLサービスを再起動します(キーワードとして2文字以上、デフォルトでは3文字)
[mysqld]
innodb_ft_min_token_size=2
3.1カスタムストップワードを設定する(つまり、単語のセグメンテーション)
USE mysql;
CREATE TABLE my_stopwords(VALUE VARCHAR(30)) ENGINE = INNODB;
INSERT INTO my_stopwords(VALUE) VALUE (',');
SET GLOBAL innodb_ft_server_stopword_table = 'mysql/my_stopwords';
〜
SHOW GLOBAL VARIABLES WHERE Variable_name IN('innodb_ft_min_token_size','innodb_ft_server_stopword_table');
+---------------------------------+--------------------+
| Variable_name | Value |
+---------------------------------+--------------------+
| innodb_ft_min_token_size | 2 |
| innodb_ft_server_stopword_table | mysql/my_stopwords |
+---------------------------------+--------------------+
3.2フルテキストインデックスを作成する
alter table article add fulltext index idx_full_keyword(keywords);
* [ ] Query OK, 0 rows affected, 1 warning (1 min 27.92 sec)
* [ ] Records: 0 Duplicates: 0 Warnings: 1
3.3残りのディスク容量は十分である必要があります。元のテーブルは4.6Gで、残りの5.7Gディスクです。フルテキストインデックスの追加も失敗します
3.4作成されたフルテキストインデックスを使用して、キーワードの出現回数をクエリする
クエリの応答時間は大幅に改善され、わずか0.05秒です。 '%Fashion%'などのキーワードに7.56秒かかります。推奨読書:MySQLパフォーマンス最適化プラクティス(非常に包括的で収集する価値があります)
3.5複数のキーワードを同時に照合する必要がある場合は、ブール全文検索を使用します
「三里屯、北京」と完全に一致するレコードの数
select count(*) from article where match(keywords) against('+三里屯,北京' in boolean mode);
+----------+
| count(*) |
+----------+
| 1 |
+----------+
1 row in set (0.06 sec)
「Sanlitun」または「Beijing」に一致するレコードの数を示します
select count(*) from article where match(keywords) against('三里屯,北京');
+----------+
| count(*) |
+----------+
| 8 |
+----------+
1 row in set (0.06 sec)
3.6フルテキストインデックスを作成した後、他のいくつかのファイルが作成されます
96K 7月5日午後04時30 FTS_00000000000000a7_00000000000000c0_INDEX_1.ibd96K 7月5日午後04時30 FTS_00000000000000a7_00000000000000c0_INDEX_2.ibd96K 7月5日午後04時30 FTS_00000000000000a7_00000000000000c0_INDEX_3.ibd96K 7月5日午後04時30 FTS_00000000000000a7_00000000000000c0_INDEX_4.ibd128K 7月5日午後04時30分FTS_00000000000000a7_00000000000000c0_INDEX_5.ibd256K 7月5日午後04時30 FTS_00000000000000a7_00000000000000c0_INDEX_6.ibd96K 7月5 16:29 FTS_00000000000000a7_BEING_DELETED_CACHE.ibd96K Jul 5 16:29 FTS_00000000000000a7_BEING_DELETED.ibd96K Jul 5 16:30 FTS_00000000000000a7_CONFIG.ibd96K Jul 5 16:29 FTS_00000000000000a7_DELETED_CACHE.ibda000000_00d000000_00d00000000000000a DELETEd_CACHE.ibd00d00K0000000000
- 最初の6つは逆索引を示します(補助索引テーブル)
- アイテム7および8は、削除されたドキュメントを含むドキュメントID(DOC_ID)を示し、そのデータは現在フルテキストインデックスから削除されています
- FULLTEXTインデックスの内部状態を示す9番目の情報
- 10番目と11番目のドキュメントには、削除されたが、データがフルテキストインデックスから削除されていないドキュメントが含まれています
Ngram単語セグメンテーションパーサーを使用して全文索引を作成する
1.タイトルフィールドにフルテキストインデックスを設定します(フィールドには固定のストップワード単語セグメンテーションがありません。ngram単語セグメンテーションパーサーを使用してください)
my.cnf構成ファイルでngram_token_sizeを設定し(デフォルトは2、ngramキーワードとして2文字)、mysqlサービスを再起動する必要があります
ここではデフォルトの2を使用します
select title from article limit 10;
+------------------------------------------------------------------------------+
| title |
+------------------------------------------------------------------------------+
| worth IT |
|Launchpad 江南皮革厂小show |
|Raw 幕后罕见一刻 “疯子”被抬回后台 |
|Raw:公子大骂老爸你就是个绿茶 公子以一打四 |
|四组30平米精装小户型,海量图片,附户型图 |
|夜店女王性感烟熏猫眼妆 |
|大秀哥重摔“巨石”强森 |
|少女时代 崔秀英 服饰科普 林允儿 黄美英 金泰妍 郑秀晶 |
|德阳户外踏青,花田自助烧烤 |
+------------------------------------------------------------------------------+
2.タイトルフィールドにフルテキストインデックスを作成する
alter table article add fulltext index ft_index_title(title) with parser ngram;
Query OK, 0 rows affected (3 min 29.22 sec)
Records: 0 Duplicates: 0 Warnings: 0
3.逆索引が作成されます(タイトルフィールドが長いほど、逆索引が大きく作成されます)
112M 7月5日21時46分FTS_00000000000000a7_00000000000000cd_INDEX_1.ibd28M 7月5日21時46分FTS_00000000000000a7_00000000000000cd_INDEX_2.ibd20M 7月5日21時46分FTS_00000000000000a7_00000000000000cd_INDEX_3.ibd140M 7月5日21時46 FTS_00000000000000a7_00000000000000cd_INDEX_4.ibd128M 7月5日21時46分FTS_00000000000000a7_00000000000000cd_INDEX_5.ibd668M 7月5日21時46 FTS_00000000000000a7_00000000000000cd_INDEX_6.ibd
4.全文索引を作成せずにタイトルのキーワードを検索する
5.フルテキストインデックスを使用してキーワードを検索する
応答時間が大幅に改善されました
6.検索されたキーワードの数が2(ngram_token_sizeで定義されたサイズ)より大きい場合、不整合があることに注意してください。
通常の検索では、キーワードが表示される実際のレコード数は6です。
全文検索、キーワード付きのレコード数は9443
キーワードが実際に表示されるレコードの数は1です
全文検索でキーワードが表示されるレコードの数は3202です
おわりに
mysqlのフィールドにストップワードの固定分詞(英語のスペース文字、「、」、「-」など)がある場合、フィールドにフルテキストインデックスが設定され、特定のキーワードの関連レコード情報をすばやく検索して、簡単な検索を実現できます。エンジン効果
mysqlフィールドに固定のストップワードワードセグメンテーションがない場合は、組み込みのパーサーngramを使用してフィールド値を固定数のキーワード(ngram_token_sizeで定義されたサイズ)に分割してクイック検索を行います;検索されたキーワードの文字数がngram_token_sizeで定義されたサイズと等しくない場合、実態と矛盾する問題があります
フルテキストインデックスはすばやく検索でき、インデックスを維持するオーバーヘッドもあります。フィールド長が大きいほど、作成されるフルテキストインデックスが大きくなり、DMLステートメントのスループットに影響します。専用のフルテキスト検索エンジンESを使用してこれを行うことができます。