WHERE content LIKE '%keyword%' —— 無法使用索引、全表掃描、不支援相關性排序、多關鍵字邏輯極其繁瑣。資料量超過萬筆即明顯卡頓,百萬級直接不可用。
MySQL 3.23.23+ 引入 Full-Text Search,透過 FULLTEXT INDEX + MATCH() AGAINST() 實現:
CREATE TABLE reviews (
id INT(5) PRIMARY KEY NOT NULL AUTO_INCREMENT,
data TEXT
) ENGINE=MyISAM; -- MySQL 5.6 前僅 MyISAM 支援,5.6+ InnoDB 也支援
INSERT INTO reviews (data) VALUES
('Gingerboy has a new single out called Throwing Rocks. It\'s great!'),
('Hello all, I really like the new Madonna single. One of the hottest tracks...'),
('Have you heard the new band Hotter Than Hell? They burn instruments...');
-- 建立全文索引
ALTER TABLE reviews ADD FULLTEXT INDEX (data);
-- 驗證
SHOW INDEXES FROM reviews;
-- Key_name: data, Index_type: FULLTEXT
-- 簡單查詢
SELECT id FROM reviews WHERE MATCH(data) AGAINST('single');
-- 返回 id 1, 2(包含 single)
-- 查看相關性分數
SELECT id, MATCH(data) AGAINST('rock') AS relevance
FROM reviews;
-- id=3 分數 1.386,id=1,2 分數 0
MATCH() 可接受多欄位:MATCH(title, body, tags)。語法:AGAINST('expression' IN BOOLEAN MODE)
| 運算子 | 含義 | 範例 |
|---|---|---|
+ | 必須包含 | +single |
- | 必須不包含 | -madonna |
* | 前綴通配(僅尾部) | hot* 匹配 hot, hotter, hottest |
"" | 精確短語 | "throwing rocks" |
() | 分組 | +apple +(pie strudel) |
~ | 降低相關性(軟排除) | ~noise |
-- 必須含 single,排除 madonna
SELECT id FROM reviews WHERE MATCH(data) AGAINST('+single -madonna' IN BOOLEAN MODE);
-- 僅 id=1
-- 前綴搜尋 hot*
SELECT id FROM reviews WHERE MATCH(data) AGAINST('hot*' IN BOOLEAN MODE);
-- id=2,3
-- 至少包含 hell 或 rocks 之一
SELECT id FROM reviews WHERE MATCH(data) AGAINST('hell rocks' IN BOOLEAN MODE);
-- id=1,3(預設 OR 邏輯)
ft_min_word_len(預設 4),中文需設為 1 或使用 ngram parser(MySQL 5.7.6+)。ft_stopword_file。ngram parser 解決無分詞問題:FULLTEXT INDEX (data) WITH PARSER ngram。DISABLE KEYS / ENABLE KEYS。FULLTEXT INDEX。WHERE col LIKE '%kw%' 為 WHERE MATCH(col) AGAINST('kw')。IN BOOLEAN MODE。ngram parser 或整合外部分詞器(如 jieba + 儲存分詞結果)。MySQL 全文搜尋以倒排索引 + 相關性排序徹底解決 LIKE 低效難題。掌握自然語言模式(智能排序)與布林模式(精準邏輯)雙模切換,並針對中文啟用 ngram parser,即可在資料庫層面實現生產級搜尋體驗。超大規模、高併發、複雜語義場景,建議升級 Elasticsearch/OpenSearch 專用搜尋引擎。