Parlons de la façon dont l'index de texte intégral MySQL résout le problème des requêtes lentes, comme celles à correspondance floue.
青灯夜游
Libérer: 2022-11-02 13:36:47
original
2759 Les gens l'ont consulté
Requête floue, telle que l'interrogation d'utilisateurs dont le nom contient "xiao", la manière courante d'écrire est comme "%xiao%", elle analysera toute la table dans MySQL, la quantité de données est petite et la totalité L'analyse des tables est également très rapide. À mesure que les données augmentent, elles ralentiront et ES sera très lourd. Cet article vous présentera la solution pour ralentir les requêtes à correspondance floue : l'index de texte intégral MySQL.
Exigences
Besoin d'une correspondance floue pour interroger un mot
select * from t_phrase Where LOCATE('chang',phrase) = 0; ) > 0;
select * from t_chinese_phrase which phrase like '%长%'
expliquez et jetez un œil au plan d'exécution
Il ressort des résultats d'explication que même si nous J'ai construit un index pour la phrase, mais lors de l'interrogation, l'index n'est pas valide.
Raison :
L'index de MySQL est une structure arborescente B+. L'utilisation par InnoDB de "%xx" lors d'une requête floue de données entraînera l'échec de l'index (je n'entrerai pas dans les détails ici)
Du point de vue du temps de requête, le temps passé : 90 ms.
Volume de données actuel : 93230 (9,3 W) nécessite déjà 90 ms. Ce temps n'est pas acceptable. Si la quantité de données augmente, ce temps continuera à augmenter.
Solution :
Lorsque la quantité de données n'est pas importante, utilisez l'index de texte intégral de MySQL ;
Lorsque la quantité de données est relativement importante ou que l'index de texte intégral de MySQL n'est pas à la hauteur des attentes, vous pouvez envisagez d'utiliser ES
Ce qui suit concerne principalement l'index de texte intégral MySQL
Introduction à l'index de texte intégral
1 Historique de développement
L'index de texte intégral de l'ancienne version de MySQL peut. ne doit être utilisé que sur les champs char, varchar et text du moteur de stockage MyISAM.
Le moteur InnoDB sur MySQL5.6.24 a également ajouté l'indexation en texte intégral.
2. Index en texte intégral
Recherche en texte intégral (Recherche en texte intégral) est une technologie permettant de trouver toute information de contenu dans l'intégralité d'un livre ou d'un article entier stocké dans la base de données. Il peut obtenir des informations sur les chapitres, les sections, les paragraphes, les mots, etc. dans le texte intégral selon les besoins, et peut également effectuer diverses statistiques et analyses
3. Créez un index de texte intégral
Si vous devez définir. Si vous créez un index de texte intégral pour une grande quantité de données, il est recommandé de l'ajouter d'abord. Les données sont ensuite indexées.
1. Créez un index de texte intégral lors de la création d'une table
2 Ajoutez un index de texte intégral à une table existantecréez le nom de l'index de texte intégral sur le nom de la table (nom du champ) ;</code. ><p></p>par exemple :<p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:sql;toolbar:false">create table t_word
(
id int unsigned auto_increment comment &#39;自增id&#39; primary key,
uid char(32) not null comment &#39;32位唯一id&#39;,
word varchar(256) null comment &#39;英文单词&#39;,
translate varchar(256) null
);
create fulltext index full_idx_translate
on t_word (translate);
create fulltext index full_idx_word
on t_word (word);
INSERT INTO t_word (id, uid, word, translate) VALUES (1, &#39;9d592499c65648b0a9519206688ef3f9&#39;, &#39;lion&#39;, &#39;狮子&#39;);
INSERT INTO t_word (id, uid, word, translate) VALUES (2, &#39;ce26ac4239514bc6af481bcb1d9b67df&#39;, &#39;panda&#39;, &#39;熊猫&#39;);
INSERT INTO t_word (id, uid, word, translate) VALUES (3, &#39;a7d6042853c44904b68275daafb44702&#39;, &#39;tiger&#39;, &#39;老虎&#39;);
INSERT INTO t_word (id, uid, word, translate) VALUES (4, &#39;f13bd0a8ecea44fc9ade1625eeb4cc3c&#39;, &#39;goat&#39;, &#39;山羊&#39;);
INSERT INTO t_word (id, uid, word, translate) VALUES (5, &#39;27d5cbfc93a046388d712085e567474f&#39;, &#39;sheep&#39;, &#39;绵羊&#39;);
INSERT INTO t_word (id, uid, word, translate) VALUES (6, &#39;ed35df138cf348aa937781be8ee21cbf&#39;, &#39;lamb&#39;, &#39;羊羔&#39;);
INSERT INTO t_word (id, uid, word, translate) VALUES (7, &#39;fba5861d9527440990276e999f47ef8f&#39;, &#39;buffalo&#39;, &#39;水牛&#39;);
INSERT INTO t_word (id, uid, word, translate) VALUES (8, &#39;3a72e76f210841b1939fff0d3d721375&#39;, &#39;bull&#39;, &#39;公牛&#39;);
INSERT INTO t_word (id, uid, word, translate) VALUES (9, &#39;272e0b28ea7a48248a86f17533bf9943&#39;, &#39;cow&#39;, &#39;母牛&#39;);
INSERT INTO t_word (id, uid, word, translate) VALUES (10, &#39;47127adface54e418e4c1b9980af6d16&#39;, &#39;calf&#39;, &#39;小牛&#39;);
INSERT INTO t_word (id, uid, word, translate) VALUES (11, &#39;10592499c65648b0a9519206688ef3f9&#39;, &#39;little lion&#39;, &#39;小狮子&#39;);
INSERT INTO t_word (id, uid, word, translate) VALUES (12, &#39;1bf095110b634a01bee5b31c5ee7ee0c&#39;, &#39;little cow&#39;, &#39;母牛&#39;);
INSERT INTO t_word (id, uid, word, translate) VALUES (13, &#39;4813e588cde54c30bd65bfdbb243ad1f&#39;, &#39;little calf&#39;, &#39;小小牛&#39;);
INSERT INTO t_word (id, uid, word, translate) VALUES (14, &#39;5e377e281ad344048b6938a638b78ccb&#39;, &#39;little bull&#39;, &#39;小公牛&#39;);
INSERT INTO t_word (id, uid, word, translate) VALUES (15, &#39;2855ad0da2964c7682c178eb8271f13d&#39;, &#39;little buffalo&#39;, &#39;小水牛&#39;);
INSERT INTO t_word (id, uid, word, translate) VALUES (16, &#39;72f24c9a77644d57a36f3bdf2b8116b0&#39;, &#39;little lamb&#39;, &#39;小羊羔&#39;);
INSERT INTO t_word (id, uid, word, translate) VALUES (17, &#39;2d592499c65648b0a9519206688ef3f9&#39;, &#39;I&#39;&#39;m a big lion&#39;, &#39;我是一只大狮子&#39;);</pre><div class="contentsignin">Copier après la connexion</div></div> </p>3. Supprimer l'index de texte intégral<p><code>create fulltext index 索引名称 on 表名(字段名);
eg:
MATCH(col1,col2,...) AGAINST(expr[search_modifier])
search_modifier:
{
IN NATURAL LANGUAGE MODE
| IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION
| IN BOOLEAN MODE
| WITH QUERY EXPANSION
}
Copier après la connexion
3、删除全文索引
alter table 表名 drop index 索引名; modifier le nom de la table supprimer le nom de l'index ;
4.1. EN MODE LANGAGE NATUREL
Le mode langage naturel est MySQL
par défaut
mode de recherche en texte intégral. Le mode langage naturel ne peut pas utiliser d'opérateurs et ne peut pas spécifier de requêtes complexes telles que des mots-clés qui doivent apparaître ou ne doivent pas apparaître.
// 默认是使用 in natural language mode
select * from t_word where match(word) against ('lion');
// 或者 显示写
select * from t_word where match(word) against ('lion' in natural language mode);
Copier après la connexion
Copier après la connexion
Les résultats sont les suivants :4.2 EN MODE BOOLÉENMode BOOLÉEN
Vous pouvez utiliser des opérateurs, qui peuvent prendre en charge des requêtes complexes telles que spécifier que les mots-clés doivent apparaître ou ne doivent pas apparaître ou si le le poids du mot-clé est élevé ou faible. Il est recommandé d'utiliser le mode booléen
Opérateur
Description
est vide
Par défaut, contient le mot
+
inclure, ce mot doit exister.
-
Exclusion, les mots ne doivent pas apparaître.
>(supérieur au signe)
Incluez et augmentez la valeur de classement, les résultats de la requête seront plus élevés
<
Incluez et réduisez la valeur de classement, les résultats de la requête seront inférieurs
()
Regroupez les mots en sous-expressions (leur permettant d'être inclus, exclus, classés, etc. en tant que groupe).
~
La valeur de classement des mots négatifs.
*
Le joker est à la fin du mot.
""
Définissez une phrase (par opposition à une liste de mots individuels, où la phrase entière correspond pour inclure ou exclure).
示例:
// 默认是使用 in natural language mode
select * from t_word where match(word) against ('lion');
// 或者 显示写
select * from t_word where match(word) against ('lion' in natural language mode);
Copier après la connexion
Copier après la connexion
// 排除包含lion记录、查询出包含cow或者little的记录,提升包含calf单词的排名,降低包含cow记录的排名,查询出以go开头的记录
select * from t_word where match(word) against ('-lion cow little >calf <cow go*' in boolean mode) ;
Copier après la connexion
好像问题都解决了, 但是问题才刚开始
回到最开始的需求,我想模糊搜索
select * from t_word where match(word) against('lio' in boolean mode);
Copier après la connexion
预期值:把包含lion的都查询出来
实际结果:啥都没有。
全匹配查询的时候能查询出来
select * from t_word where match(translate) against('小水牛' in boolean mode);
Copier après la connexion
只查询部分查询不出来。如:下面只查询 "小水" 或者"水牛" 都没有数据
select * from t_word where match(translate) against('小水' in boolean mode);
# test: 库名 t_chinese_phrase: 表名字
SET GLOBAL innodb_ft_aux_table="test/t_chinese_phrase";
# 查询分词情况
SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE;
# 查询分词情况
select * from information_schema.innodb_ft_index_table;
Copier après la connexion
查询结果如下:
因为我们上面设置了分词数是1,所以,可以看到都是按照一个词进行分词的。
字段解析: FIRST_DOC_ID :word第一次出现的文档ID LAST_DOC_ID : word最后一次出现的文档ID DOC_COUNT :含有word的文档个数 DOC_ID :当前文档ID POSITION : word 当在前文档ID的位置
查询
1、使用自然语言模式 NATURAL LANGUAGE MODE 查询
在自然语言模式(NATURAL LANGUAGE MODE)下,文本的查询被转换为n-gram分词查询的并集。
SELECT * FROM t_chinese_phrase WHERE MATCH (phrase) AGAINST ('繁荣昌盛' in boolean mode) ;
Copier après la connexion
实际使用
回到我们最开始的查询需求,看看实际的效果
查询包含了“昌”的数据
SELECT * FROM t_chinese_phrase WHERE MATCH (phrase) AGAINST ('昌' IN boolean MODE) ;
SELECT * FROM t_chinese_phrase WHERE MATCH (phrase) AGAINST ('昌' ) order by id asc;
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn