MySQL模糊查詢?cè)僖灿貌恢?like+% 了!
閱讀本文大概需要 7 分鐘。
來自:juejin.cn/post/6989871497040887845
前言
%xx" 會(huì)導(dǎo)致索引失效,但有時(shí)需求就是如此,類似這樣的需求還有很多,例如,搜索引擎需要根基用戶數(shù)據(jù)的關(guān)鍵字進(jìn)行全文查找,電子商務(wù)網(wǎng)站需要根據(jù)用戶的查詢條件,在可能需要在商品的詳細(xì)介紹中進(jìn)行查找,這些都不是B+樹索引能很好完成的工作。倒排索引
inverted file index:{單詞,單詞所在文檔的id}full inverted index:{單詞,(單詞所在文檔的id,再具體文檔中的位置)}

相比之下,full inverted index 占用了更多的空間,但是能更好的定位數(shù)據(jù),并擴(kuò)充一些其他搜索特性。

全文檢索
創(chuàng)建全文索引
1、創(chuàng)建表時(shí)創(chuàng)建全文索引語法如下:
CREATE?TABLE?table_name?(?id?INT?UNSIGNED?AUTO_INCREMENT?NOT?NULL?PRIMARY?KEY,?author?VARCHAR(200),?
title?VARCHAR(200),?content?TEXT(500),?FULLTEXT?full_index_name?(col_name)?)?ENGINE=InnoDB;
SELECT?table_id,?name,?space?from?INFORMATION_SCHEMA.INNODB_TABLES
WHERE?name?LIKE?'test/%';

2、在已創(chuàng)建的表上創(chuàng)建全文索引語法如下:
CREATE?FULLTEXT?INDEX?full_index_name?ON?table_name(col_name);
使用全文索引
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
}
MATCH()?AGAINST()語法進(jìn)行,其中,MATCH()采用逗號(hào)分隔的列表,命名要搜索的列。AGAINST()接收一個(gè)要搜索的字符串,以及一個(gè)要執(zhí)行的搜索類型的可選修飾符。全文檢索分為三種類型:自然語言搜索、布爾搜索、查詢擴(kuò)展搜索,下面將對(duì)各種查詢模式進(jìn)行介紹。Natural Language
MATCH()默認(rèn)采用 Natural Language 模式,其表示查詢帶有指定關(guān)鍵字的文檔。SELECT
????count(*)?AS?count?
FROM
????`fts_articles`?
WHERE
????MATCH?(?title,?body?)?AGAINST?(?'MySQL'?);

SELECT
????count(IF(MATCH?(?title,?body?)?
????against?(?'MySQL'?),?1,?NULL?))?AS?count?
FROM
????`fts_articles`;
SELECT
????*,
????MATCH?(?title,?body?)?against?(?'MySQL'?)?AS?Relevance?
FROM
????fts_articles;

word 是否在文檔中出現(xiàn) word 在文檔中出現(xiàn)的次數(shù) word 在索引列中的數(shù)量 多少個(gè)文檔包含該 word
查詢的 word 在 stopword 列中,忽略該字符串的查詢 查詢的 word 的字符長(zhǎng)度是否在區(qū)間 [ innodb_ft_min_token_size,innodb_ft_max_token_size] 內(nèi)
SELECT
????*,
????MATCH?(?title,?body?)?against?(?'for'?)?AS?Relevance?
FROM
????fts_articles;

innodb_ft_min_token_size?和?innodb_ft_max_token_size控制 InnoDB 引擎查詢字符的長(zhǎng)度,當(dāng)長(zhǎng)度小于innodb_ft_min_token_size?或者長(zhǎng)度大于innodb_ft_max_token_size?時(shí),會(huì)忽略該詞的搜索。在 InnoDB 引擎中,參數(shù)?innodb_ft_min_token_size?的默認(rèn)值是3,innodb_ft_max_token_size的默認(rèn)值是84Boolean
select?*?from?fts_test?where?MATCH(content)?AGAINST('+Pease?-hot'?IN?BOOLEAN?MODE);
+:表示該 word 必須存在-:表示該 word 必須不存在(no operator)表示該 word 是可選的,但是如果出現(xiàn),其相關(guān)性會(huì)更高@distance表示查詢的多個(gè)單詞之間的距離是否在 distance 之內(nèi),distance 的單位是字節(jié),這種全文檢索的查詢也稱為 Proximity Search,如?MATCH(context) AGAINST('"Pease hot"@30' IN BOOLEAN MODE)語句表示字符串 Pease 和 hot 之間的距離需在30字節(jié)內(nèi)>:表示出現(xiàn)該單詞時(shí)增加相關(guān)性<:表示出現(xiàn)該單詞時(shí)降低相關(guān)性~:表示允許出現(xiàn)該單詞,但出現(xiàn)時(shí)相關(guān)性為負(fù)*?:表示以該單詞開頭的單詞,如 lik*,表示可以是 lik,like,likes"?:表示短語
SELECT
????*?
FROM
????`fts_articles`?
WHERE
????MATCH?(?title,?body?)?AGAINST?(?'+MySQL?-YourSQL'?IN?BOOLEAN?MODE?);

SELECT
????*?
FROM
????`fts_articles`?
WHERE
????MATCH?(?title,?body?)?AGAINST?(?'MySQL?IBM'?IN?BOOLEAN?MODE?);

SELECT
????*?
FROM
????`fts_articles`?
WHERE
????MATCH?(?title,?body?)?AGAINST?(?'"DB2?IBM"@3'?IN?BOOLEAN?MODE?);
SELECT
????*?
FROM
????`fts_articles`?
WHERE
????MATCH?(?title,?body?)?AGAINST?(?'+MySQL?+(>database??IN?BOOLEAN?MODE?);

SELECT
????*?
FROM
????`fts_articles`?
WHERE
????MATCH?(?title,?body?)?AGAINST?(?'MySQL?~database'?IN?BOOLEAN?MODE?);

SELECT
????*?
FROM
????`fts_articles`?
WHERE
????MATCH?(?title,?body?)?AGAINST?(?'My*'?IN?BOOLEAN?MODE?);

SELECT
????*?
FROM
????`fts_articles`?
WHERE
????MATCH?(?title,?body?)?AGAINST?(?'"MySQL?Security"'?IN?BOOLEAN?MODE?);

Query Expansion
implied knowledge通過在查詢語句中添加?WITH QUERY EXPANSION / IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION可以開啟?blind query expansion(又稱為 automatic relevance feedback),該查詢分為兩個(gè)階段。第一階段:根據(jù)搜索的單詞進(jìn)行全文索引查詢 第二階段:根據(jù)第一階段產(chǎn)生的分詞再進(jìn)行一次全文檢索的查詢
--?創(chuàng)建索引
create?FULLTEXT?INDEX?title_body_index?on?fts_articles(title,body);
--?使用?Natural?Language?模式查詢
SELECT
????*?
FROM
????`fts_articles`?
WHERE
????MATCH(title,body)?AGAINST('database');

--?當(dāng)使用?Query?Expansion?模式查詢
SELECT
????*?
FROM
????`fts_articles`?
WHERE
????MATCH(title,body)?AGAINST('database'?WITH?QUERY?expansion);

刪除全文索引
1、直接刪除全文索引語法如下:
DROP?INDEX?full_idx_name?ON?db_name.table_name;
2、使用 alter table 刪除全文索引語法如下:
ALTER?TABLE?db_name.table_name?DROP?INDEX?full_idx_name;
推薦閱讀:
Chrome 瀏覽器全球大翻車?讓 20 多億用戶無網(wǎng)可上
內(nèi)容包含Java基礎(chǔ)、JavaWeb、MySQL性能優(yōu)化、JVM、鎖、百萬并發(fā)、消息隊(duì)列、高性能緩存、反射、Spring全家桶原理、微服務(wù)、Zookeeper、數(shù)據(jù)結(jié)構(gòu)、限流熔斷降級(jí)......等技術(shù)棧!
?戳閱讀原文領(lǐng)取!? ? ? ? ? ? ? ??? ??? ? ? ? ? ? ? ? ? ?朕已閱?
評(píng)論
圖片
表情

