Sphinx/Manticore 的查詢執行遵循標準資訊檢索流程,每階段可透過配置與 SphinxQL 語法精細控制:
使用者輸入的查詢字串經過 SphinxQL 解析器處理:
wordforms、exceptions、stopwords 等規則-- SphinxQL 查詢範例
SELECT * FROM my_index
WHERE MATCH('@title 機器學習 @content (教程|入門) -過時')
OPTION ranker=bm25, max_matches=1000;
查詢詞經歷與索引建立相同的語言處理管線,確保匹配一致性:
charset_table 映射(全形→半形、大寫→小寫)morphology 規則(stemmer/lemmatizer)stopwords 列表中的詞關鍵原則:查詢端處理必須與索引端完全一致,否則會導致「明明有資料卻搜不到」的問題。
核心檢索階段,在倒排索引中定位符合條件的文件:
max_matches 限制候選集大小,避免全量掃描-- 內部執行邏輯示意
候選集 = PostingList('機器') ∩ PostingList('學習') -- @title 欄位
候選集 = 候選集 ∪ (PostingList('教程') ∪ PostingList('入門')) -- @content 欄位
候選集 = 候選集 - PostingList('過時')
候選集 = 候選集 ∩ 屬性過濾(category_id IN (1,2,3))
候選集 = TopN(候選集, max_matches=1000)
對候選文件計算分數並排序,支援多種 Ranker:
| Ranker | 特點 | 適用場景 |
|---|---|---|
| BM25(預設) | 經典 TF-IDF 變體,平衡詞頻與文件長度 | 通用全文搜尋 |
| SPH_RANK_PROXIMITY_BM25 | 結合詞距離與 BM25 | Phrase/鄰近度查詢重要時 |
| SPH_RANK_EXPR | 自定義算術表達式 | 需結合業務權重(如熱度、時間、價格) |
| SPH_RANK_NONE | 不計算分數,僅按屬性排序 | 純屬性排序、效能極致要求 |
| 策略 | 說明 | 配置/語法 |
|---|---|---|
| 限制候選集 | 避免全量掃描,降低 CPU/記憶體 | OPTION max_matches=1000 |
| 欄位權重 | 標題匹配權重高於內容 | OPTION field_weights=(title=10, content=1) |
| 快速拒絕 | 先套用選擇性高的屬性過濾 | WHERE 子句順序、索引欄位順序 |
| 查詢快取 | 重複查詢直接回傳結果 | qcache_max_bytes, qcache_thresh_msec |
| 分散式並行 | 分片並行查詢再合併 | Distributed Index + dist_threads |
-- 關鍵字建議(基於索引詞頻)
CALL SUGGEST('機器學', 'my_index', 5 AS limit, 1 AS max_edits);
-- 同義詞展開查詢
SELECT * FROM my_index WHERE MATCH('@(title,content) (手機|智慧型手機)');
-- 查看查詢計畫
SHOW PLAN FOR SELECT * FROM my_index WHERE MATCH('關鍵字');
-- 查看排名資訊
SELECT *, WEIGHT(), PACKEDFACTORS() FROM my_index WHERE MATCH('關鍵字') OPTION ranker=expr('bm25');
-- 監控慢查詢
-- log 查詢時間 > 100ms 的查詢
query_log_min_msec = 100
掌握四步驟管線,就能從根源優化搜尋體驗:解析階段調整語法支援、語言階段確保分詞一致、匹配階段控制候選集大小、排序階段注入業務邏輯。這才是搜尋引擎調優的正確打開方式。