首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 全文索引實戰指南:建立、配置、50% 閾值陷阱、布爾模式與中文分詞 (SCWS) 整合

     編輯:MySQL 資料庫相關知識

大數據模糊搜尋的關鍵技術:MySQL Fulltext Index 從入門到避坑

全文索引是關聯式資料庫內建的倒排索引機制,適合**中小規模文本搜尋** (千萬級以內)。本文涵蓋建立條件、my.cnf 配置、自然語言/布爾模式、50% 閾值陷阱、中文分詞整合 (SCWS) 完整實戰流程。

適用場景與限制

  • ✅ 適用:文章搜尋、商品標題/描述檢索、日誌關鍵字查詢、郵件內容搜尋。
  • ❌ 不適用:億級文檔、實時性極高、複雜語義分析、多語言混排 (需 Elasticsearch/Solr)。
  • 🔒 限制:僅 MyISAM (5.6 前) / MyISAM + InnoDB (5.6+);欄位類型 `CHAR`/`VARCHAR`/`TEXT`;最小詞長 `ft_min_word_len` (預設 4);停用詞表預設英文。

建立全文索引

-- 建表時指定
CREATE TABLE temp (
  id INT AUTO_INCREMENT PRIMARY KEY,
  `char` CHAR(50) NOT NULL,
  `varchar` VARCHAR(50) NOT NULL,
  `text` TEXT NOT NULL,
  FULLTEXT KEY ft_char (`char`),
  FULLTEXT KEY ft_varchar (`varchar`),
  FULLTEXT KEY ft_text (`text`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

-- 既有表新增
ALTER TABLE temp ADD FULLTEXT INDEX ft_char (`char`);

圖形工具 (phpMyAdmin/Workbench/DBeaver) 中對應「全文索引」/「Fulltext」勾選項。

關鍵配置:my.cnf / my.ini

[mysqld]
# 最小索引詞長 (預設 4,中文建議 1 或 2)
ft_min_word_len = 1
# 停用詞表 (預設內建英文,中文可指定空檔案禁用)
ft_stopword_file = ''
# 布爾模式運算子 (可自訂)
ft_boolean_syntax = '+ -><()~*:""&|'

修改後必須重啟 MySQL 並重建索引 (`REPAIR TABLE tbl QUICK` 或 `ALTER TABLE tbl DROP INDEX ft_xxx, ADD FULLTEXT INDEX ft_xxx (...)`)。

查詢語法:自然語言 vs 布爾模式

1. 自然語言模式 (預設)

SELECT * FROM temp WHERE MATCH(`char`) AGAINST ('a bc 知道');
  • **相關性排序**:按詞頻、文檔頻率、長度計算分數。
  • **50% 閾值陷阱**:若某詞出現在 **超過 50% 文檔**,視為「常見詞」自動忽略,**查無結果**。
  • 適合:自由文本搜尋、相關性排序。

2. 布爾模式 (IN BOOLEAN MODE)

-- 強制包含 'a',忽略 50% 閾值
SELECT * FROM temp WHERE MATCH(`char`) AGAINST ('a' IN BOOLEAN MODE);

-- 運算子範例
'+apple +juice'      -- 必須同時包含
'+apple -pie'        -- 包含 apple 但不含 pie
'apple*'             -- 前綴匹配 (apple, apples, applet)
'"apple juice"'      -- 精確短語
'~apple'             -- 降低相關性 (軟排除)
'+apple +(>juice 
  • **不計算相關性**,不排序 (除非手動 `ORDER BY`)。
  • **繞過 50% 閾值**,適合精確過濾、關鍵字必含場景。
  • **不支援通配符 `%`**,用 `*` 代替前綴匹配。

實測 50% 閾值陷阱與破解

-- 初始 1 筆資料:'a bc 我 知道 1 23'
-- 搜尋 'a' → 0 結果 (100% > 50%)
-- 插入 3 筆雜湊資料稀釋
INSERT INTO temp (`char`) VALUES ('7'), ('7'), ('x');
-- 再搜尋 'a' → 1 結果 (25% < 50%)

生產環境破解方案:

  1. **優先用布爾模式** `IN BOOLEAN MODE` (無 50% 限制)。
  2. **定期插入雜湊/噪音資料** 稀釋熱門詞頻 (不推薦,污染資料)。
  3. **調大 `ft_min_word_len`** 讓短詞不被索引 (犧牲精度)。
  4. **遷移至 Elasticsearch** (根治)。

中文分詞整合:SCWS (Simple Chinese Word Segmentation)

MySQL 內建無中文分詞,**必須應用層分詞後寫入**,查詢時同樣分詞。

安裝步驟 (Windows + PHP 範例)

  1. 下載:`php_scws.dll` (對應 PHP 版本/TS/NTS)、`dict.xdb` 詞典、規則集 `.ini`。
  2. 建立目錄 `D:\scws`,解壓詞典與規則集至此。
  3. 複製 `php_scws.dll` 至 PHP `ext` 目錄。
  4. 修改 `php.ini`:
    [scws]
    extension = php_scws.dll
    scws.default.charset = utf8
    scws.default.fpath = "D:\\scws"
  5. 重啟 Web 服務 (Apache/Nginx + PHP-FPM)。

PHP 分詞調用範例

$str = "測試中文分詞";
$so = scws_new();
$so->send_text($str);
$so->set_charset('utf8');
$so->set_dict('D:/scws/dict.xdb');
$so->set_rule('D:/scws/rules.utf8.ini');
$result = $so->get_result();
$so->close();

/* $result 結構:
Array(
  [0] => Array( word => '測試', idf => 3.2, attr => 'n', off => 0, len => 2 ),
  [1] => Array( word => '中文', idf => 4.1, attr => 'n', off => 2, len => 2 ),
  [2] => Array( word => '分詞', idf => 5.0, attr => 'v', off => 4, len => 2 )
) */

// 寫入資料庫:用空格或逗號連接詞彙
$keywords = implode(' ', array_column($result, 'word'));
// INSERT ... SET keywords = '$keywords'

全文索引應用流程總結

寫入路徑: 接收原文 → SCWS 分詞 → 詞彙以空格連接 → 寫入 FULLTEXT 欄位

查詢路徑: 接收關鍵字 → SCWS 分詞 → 組裝布爾模式查詢 (如 `+詞1 +詞2`) → MATCH ... AGAINST (IN BOOLEAN MODE)

效能與維護建議

  • 定期 `OPTIMIZE TABLE` 整理碎片 (全文索引碎片化快)。
  • 監控 `FULLTEXT` 索引大小:`SHOW TABLE STATUS` → `Index_length`。
  • 大表考慮分表/分庫,或遷移 Elasticsearch。
  • 停用詞表 `ft_stopword_file` 指定中文停用詞 (的、了、在、是...)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved