MySQL 原生查詢單執行緒,面對 32 核心、16 顆 SSD 的強悍伺服器,單查詢僅能佔用 1 核心 + 1 磁碟,資源利用率 < 5%。Sphinx 內建的 分散式索引 機制,原本為跨機器水平擴展設計,巧妙映射到單機多核場景,僅修改設定檔即可讓查詢速度提升 N 倍(N = 切分分片數),且索引建立也能並行化。
id % N 切分為 N 個 local 索引(分片)。type=distributed 總索引聚合這 N 個分片。searchd 設定 dist_threads = N,查詢時並行向 N 個分片發請求、合併結果。indexer 同樣可 --rotate 並行重建 N 個分片索引。source src_base
{
type = mysql
sql_host = localhost
sql_user = sphinx
sql_pass = *****
sql_db = mydb
sql_query_pre = SET NAMES utf8mb4
sql_query = SELECT id, title, content, created_at FROM articles
}
# 分片 0
source src_p0 : src_base
{
sql_query = SELECT id, title, content, created_at FROM articles WHERE id % 3 = 0
}
# 分片 1
source src_p1 : src_base
{
sql_query = SELECT id, title, content, created_at FROM articles WHERE id % 3 = 1
}
# 分片 2
source src_p2 : src_base
{
sql_query = SELECT id, title, content, created_at FROM articles WHERE id % 3 = 2
}
index idx_template
{
type = plain
source = src_base
path = /var/lib/sphinx/idx
morphology = stem_enru
min_word_len = 1
}
index idx_p0 : idx_template { source = src_p0 }
index idx_p1 : idx_template { source = src_p1 }
index idx_p2 : idx_template { source = src_p2 }
# 總索引:應用端只查這個
index idx_articles
{
type = distributed
local = idx_p0
local = idx_p1
local = idx_p2
# 也可加 remote = ... 擴展到多機
}
searchd
{
listen = 9312
listen = 9306:mysql41
log = /var/log/sphinx/searchd.log
query_log = /var/log/sphinx/query.log
read_timeout = 5
max_children = 30
dist_threads = 3 # 關鍵:並行查詢執行緒數 = 分片數
workers = threads # 執行緒模式
binlog_path = /var/lib/sphinx/binlog
}
# 首次建立 (可並行跑 3 個終端機)
indexer --config /etc/sphinx/sphinx.conf idx_p0 --rotate
indexer --config /etc/sphinx/sphinx.conf idx_p1 --rotate
indexer --config /etc/sphinx/sphinx.conf idx_p2 --rotate
# 之後增量/全量重建同理,或寫腳本並行觸發
| 指標 | 單索引 | 3 分片 + dist_threads=3 |
|---|---|---|
| 查詢延遲 (P99) | 120 ms | 45 ms |
| CPU 利用率 | 3% | ~85% |
| 索引建立時間 | 180 s | 65 s (並行) |
注意:合併階段 (dist_threads 之後) 仍為單執行緒,涉及大量 ORDER BY/GROUP BY/COUNT(*) 時會成瓶頸。對策:
• 盡量在分片層完成過濾/排序(sql_query 加 ORDER BY)。
• 避免 LIMIT 1000000 深分頁,改用 Keyset 分頁。
• 觀察 query_log 中 merged 耗時,若佔比 > 30% 需優化。
sphinx_shard(id_start, id_end, shard_id),搭配 sql_query_range / sql_range_step,適合非連續 ID、需熱冷分離場景。readonly=1 節省合併開銷。path 指向不同掛載點。結語:Sphinx 分散式索引「單機多核化」是零程式碼、零架構變更的效能倍增器。配合 dist_threads、workers=threads、合理切分鍵,即可將閒置 CPU/IO 變為查詢吞吐量。下一步可探索 real-time index (RT) 實現準即時寫入,或接入 Manticore Search (Sphinx 分支) 獲得更積極的功能更新。