痛點分析
- MySQL 內建 FULLTEXT 僅支持空格分詞語言(英文等)
- 中文無分隔符,直接建索引將整段文本視為一個 Token,檢索失效
LIKE '%關鍵字%' 全表掃描,十萬級數據耗時 10 秒+,體驗極差
解決方案架構:分詞 → 編碼 → FULLTEXT
用戶輸入中文 → SCWS 分詞 → URLEncode 編碼 → 空格連接 → 寫入 FULLTEXT 索引表
↑
搜索時同樣處理,直接 MATCH AGAINST
核心組件
1. 雙表結構
-- 業務表
CREATE TABLE members (
user_id INT PRIMARY KEY,
user_name VARCHAR(50),
user_introduction TEXT
) ENGINE=InnoDB;
-- 索引表 (僅存編碼後 Token)
CREATE TABLE members_index (
user_id INT PRIMARY KEY,
index_intro TEXT,
FULLTEXT INDEX ft_intro (index_intro)
) ENGINE=MyISAM; -- 5.6 前 FULLTEXT 僅 MyISAM 支持
2. SCWS 中文分詞 (PHP 擴展)
function str_fc($str) {
$so = scws_new();
$so->set_charset('utf8');
$so->send_text($str);
$mystr = '';
while ($tmp = $so->get_result()) {
foreach ($tmp as $ss) {
$s = trim($ss['word']);
if ($s) $mystr .= $s . ' ';
}
}
return $mystr;
}
3. 編碼與去重存儲
$tokens = str_fc($intro); // "北京 大學 計算機 系 "
$arr = array_filter(explode(' ', $tokens)); // 去空
$arr = array_flip(array_flip($arr)); // 去重
$encoded = '';
foreach ($arr as $token) {
if (strlen($token) > 1) { // 單字過濾可選
$encoded .= str_replace('%', '', urlencode($token)) . ' ';
}
}
// $encoded 如: "E58C97E4BAACE5A4A7E5ADA6 E8AEA1E7AE97E69CBA E7B3BB "
// 存入 members_index.index_intro
關鍵點:urlencode 產生的 % 是 MySQL 通配符,**必須移除**,否則 MATCH 語法錯誤。
4. 搜索流程
-- 用戶輸入 "北京 大學"
$kw_encoded = str_replace('%', '', urlencode(str_fc('北京 大學')));
// "E58C97E4BAACE5A4A7E5ADA6 "
-- SQL
SELECT m.* FROM members m
JOIN members_index mi ON m.user_id = mi.user_id
WHERE MATCH(mi.index_intro) AGAINST('$kw_encoded' IN BOOLEAN MODE);
性能與優化
| 指標 | 優化前 (LIKE) | 優化後 (FULLTEXT) |
| 10萬條數據查詢耗時 | ~10 秒 | < 0.5 秒 |
| 索引體積 | 無 | 原文本 ~30-50% |
| 實時性 | 即時 | 需同步更新索引表 |
生產級增強方案
- 異步更新:業務寫入 → 消息隊列 → Worker 分詞編碼更新索引表,解耦寫入延遲
- 增量重建:定期
OPTIMIZE TABLE members_index 整理碎片
- 停用詞過濾:分詞階段過濾「的、了、在」等高頻無意義詞
- 權重區分:標題/標籤 權重 > 正文,可構造
index_intro = title_tokens*3 + tag_tokens*2 + body_tokens
- 遷移建議:MySQL 5.7.6+ / 8.0 內建 ngram parser,
CREATE FULLTEXT INDEX ft ON t(col) WITH PARSER ngram; 免去外部分詞依賴
替代方案對比
| 方案 | 優勢 | 劣勢 | 適用場景 |
| MySQL ngram (5.7+) | 零依賴、原生、實時 | 索引大、不支持詞級精準匹配 | 中小型、避免外部組件 |
| Elasticsearch | 專業分詞、分布式、聚合分析 | 運維複雜、數據同步延遲 | 大規模、復雜檢索需求 |
| Sphinx/Manticore | MySQL 友好、增量索引、SQL 接口 | 功能較 ES 弱 | MySQL 深度綁定、近實時 |
| 本文方案 (分詞+編碼) | 輕量、無新組件、MySQL 5.1+ 通用 | 需維護同步、編碼體積大 | 舊版本遷移、輕量級項目 |
- 上一篇文章: MySQL NDB Cluster 搭建實戰:管理節點、數據節點與 SQL 節點三層架構部署
- 下一篇文章: MySQL 慢查詢日志配置、分析與優化實戰指南
Copyright ©
程式碼之家 All Rights Reserved