MySQL 內建全文搜尋支援 MyISAM 引擎(5.6+ InnoDB 也支援),透過 MATCH() ... AGAINST() 語法實現自然語言、布林、查詢擴展三種模式。本文涵蓋前置條件、中文分詞配置、索引建立、三種模式語法差異、效能優化建議,並介紹第三方中文分詞插件(海量科技)整合方案。
[mysqld]
ft_min_word_len = 2 # 最小索引詞長度,預設 4,中文單字需改 2
ft_wordlist_charset = gbk # 詞典字元集 (utf8/gbk/big5)
ft_wordlist_file = /path/wordlist-gbk.txt # 詞表檔 (詞+詞頻)
ft_stopword_file = /path/stopwords-gbk.txt # 停用詞表 (每行一詞)
修改後必須重啟 MySQL 並重建全文索引 (REPAIR TABLE / ALTER TABLE ... DROP INDEX ... ADD FULLTEXT)。
-- 建表時
CREATE TABLE articles (
id INT PRIMARY KEY,
title VARCHAR(200),
body TEXT,
FULLTEXT KEY ft_title_body (title, body)
) ENGINE=MyISAM;
-- 既有表
ALTER TABLE articles ADD FULLTEXT INDEX ft_tags (tags);
-- 或
CREATE FULLTEXT INDEX ft_tags ON articles(tags);
| 模式 | 語法 | 特點 | 適用場景 |
|---|---|---|---|
| 自然語言 (預設) | MATCH(col) AGAINST('keyword')... AGAINST('keyword' IN NATURAL LANGUAGE MODE) |
忽略停用詞、50% 門檻法(出現超過 50% 行視為停用詞)、自動按相關度降序、僅獨立單詞匹配 | 一般關鍵字搜尋、相關度排序 |
| 布林模式 | MATCH(col) AGAINST('keyword' IN BOOLEAN MODE) |
無 50% 門檻、支援運算子 + - * " " () ~、支援部分匹配、不自動排序(需自行 ORDER BY) | 精確控制、排除詞、前綴匹配、複雜邏輯 |
| 查詢擴展 | MATCH(col) AGAINST('keyword' WITH QUERY EXPANSION)或 IN BOOLEAN MODE WITH QUERY EXPANSION |
兩階段:先自然語言搜尋 → 取高相關度行提取關鍵詞 → 再次搜尋 | 關鍵詞較少、需擴大召回率 |
+word 必須包含
-word 必須不包含
word 可選(較高相關度)
>word 提高相關度
-- 自然語言:尋找包含「旅遊」的文章,按相關度排序
SELECT * FROM articles WHERE MATCH(tags) AGAINST('旅遊');
-- 布林:必須包含「台灣」,不可包含「機票」,前綴匹配「飯店*」
SELECT * FROM articles
WHERE MATCH(title, body) AGAINST('+台灣 -機票 飯店*' IN BOOLEAN MODE)
ORDER BY MATCH(title, body) AGAINST('+台灣 -機票 飯店*' IN BOOLEAN MODE) DESC;
-- 查詢擴展:關鍵詞「資料庫」擴展搜尋
SELECT * FROM articles
WHERE MATCH(body) AGAINST('資料庫' WITH QUERY EXPANSION);
LOAD DATA → CREATE FULLTEXT INDEX。ft_min_word_len 適應中文單字(2),但會增加索引體積。ngram 解析器(需 WITH PARSER ngram),配置不同。groupadd mysql
useradd -g mysql mysql
cd /usr/local
gunzip < mysql-chplus-5.0.37-linux-i686.tar.gz | tar xvf -
ln -s /usr/local/mysql-chplus-5.0.37 /usr/local/mysql
cd mysql
scripts/mysql_install_db --user=mysql
chown -R mysql data
chown -R mysql .
/usr/local/mysql/bin/mysqld_safe --user=mysql &
測試:
CREATE TABLE test (
testid INT(4) NOT NULL,
testtitle VARCHAR(256),
testbody VARCHAR(256),
FULLTEXT(testtitle, testbody)
);
INSERT INTO test VALUES (NULL, '你好嗎', '測試你好嗎'), (NULL, '好你好', '好你好');
SELECT * FROM test WHERE MATCH(testtitle, testbody) AGAINST('你好' IN BOOLEAN MODE);
MySQL 5.1 全文搜尋中文手冊:dev.mysql.com/doc/refman/5.1/zh/functions.html#fulltext-search
掌握 MATCH AGAINST 三大模式與中文分詞配置,即可在 MySQL 內建全文搜尋滿足大多數中文搜尋需求;若追求極致準確度,可整合海量等專業分詞引擎。