Sphinx 配置的核心就三件事:source 段写清数据从哪来,index 段定好怎么切词和存索引,searchd 段管住进程端口和内存开销,中文场景再多加一步 charset_table 与 ngram 的处理。
下面按实际部署顺序拆开讲,每一步都给出可直接照抄的配置片段和命令。
Sphinx 配置文件怎么设置:sphinx.conf 的三段式结构
sphinx.conf 是纯文本,用类似 C 的大括号语法分块,一个能跑起来的最小配置,包含 source、index、searchd 三类段。
source 段:数据来源的声明
source src_article
{
type = mysql
sql_host = 127.0.0.1
sql_user = sphinx_ro
sql_pass = 你的密码
sql_db = cms
sql_port = 3306
sql_query = SELECT id, title, content, cat_id, UNIX_TIMESTAMP(created_at) AS created_at
FROM articles WHERE status = 1
sql_attr_uint = cat_id
sql_attr_timestamp = created_at
}
几个容易踩的点:
sql_query返回的第一列必须是大整数主键,Sphinx 拿它当文档 ID,重复或非整数都会报错。- 需要用来排序、过滤、分组的字段,必须用
sql_attr_显式声明成属性,否则查不到也排不了。 - 参与全文检索的文本字段不用声明,出现在 SELECT 里就自动被索引。
- 表数据量大时,加上
sql_query_range和sql_range_step,让 indexer 分批拉取,避免一条 SQL 把数据库连接压死。
index 段:决定检索能力的上限
index idx_article
{
source = src_article
path = /var/lib/sphinx/data/article
docinfo = extern
mlock = 0
morphology = stem_en
min_word_len = 1
html_strip = 1
charset_table = 0..9, A..Z->a..z, a..z
}
docinfo = extern 把属性数据放到磁盘文件,内存占用会明显下降;mlock = 1 会把索引锁在内存里,查询更快但吃内存,机器紧张时不要开。
searchd 段:服务进程参数
searchd { listen = 9312 listen = 9306:mysql41 log = /var/log/sphinx/searchd.log query_log = /var/log/sphinx/query.log pid_file = /var/run/searchd.pid max_matches = 1000 seamless_rotate = 1 binlog_path = /var/lib/sphinx/data }
9312 是原生 API 端口,9306 是 SphinxQL 端口后者兼容 MySQL 协议,可以直接用 mysql 客户端连上去调试:
indexer --config /etc/sphinx/sphinx.conf --all
searchd --config /etc/sphinx/sphinx.conf
mysql -h127.0.0.1 -P9306
Sphinx 中文分词配置:为什么你的搜索搜不到中文
这是新手最容易卡住的地方,Sphinx 自身不携带中文词典,默认按字符编码切分,中文文本会被切成一堆无意义的碎片,搜索自然无结果。
目前主流的三种解法:
- ngram 方案,在 charset_table 里加入中文字符区间,同时打开 ngram,配置如下:
charset_table = 0..9, A..Z->a..z, a..z, U+4E00..U+9FA5
ngram_len = 1
ngram_chars = U+4E00..U+9FA5
优点是配置简单、无需外部依赖;代价是索引体积会膨胀,且单字切分带来大量误召回,适合标题短、查询词短的站内搜索。
-
外部预处理方案,数据入库前用 jieba、SCWS 之类的分词器处理,把结果以空格分隔写进一个冗余字段,Sphinx 侧按空格切词即可,精度明显更好,但要维护词典,新增热词得同步更新。
-
换用 Manticore Search,Sphinx 3.x 转为闭源后,社区分叉出的 Manticore Search 延续了开源路线,内置 ICU 分词,配置里一行
morphology = icu就能处理中日韩文本,省掉前面的折腾。
不论选哪种,改完分词相关参数后必须全量重建索引,否则新旧词典混用会导致搜索行为不可预测。
Sphinx 和 Elasticsearch 有什么区别:选型看四个维度
| 维度 | Sphinx / Manticore | Elasticsearch |
|---|---|---|
| 资源占用 | 单进程,常驻内存较小,2 核 4G 可跑中小规模索引 | JVM 常驻,堆内存建议不低于 2G |
| 部署复杂度 | 一个二进制加一个配置文件 | 集群、节点角色、分片与副本规划 |
| 中文支持 | 需 ngram 或外部预处理 | 插件生态成熟,内置多种中文分词器 |
| 实时性 | RT 索引配 binlog 可做到秒级 | 近实时,默认刷新间隔约 1 秒 |
| 分布式 | 单机为主,横向扩展要自己做 | 原生分片与集群管理 |
据 DB-Engines 数据库流行度榜单,Elasticsearch 长期处在全文检索类目的头名,生态和文档量级都占优,行业共识认为,日增文档在百万级以下、团队没有专职搜索运维的站内搜索场景,Sphinx 的部署成本和资源占用更划算;一旦涉及多租户、复杂聚合与水平扩展,ES 的省心程度会反超。
Sphinx 搭建站内搜索要多少钱:成本拆解
很多人关心这个,其实账很好算:
- 软件授权:Sphinx 与 Manticore Search 均为开源项目,自用不产生授权费,只有需要闭源分发时才涉及商业授权话题。
- 服务器:国内主流云厂商 2 核 4G 规格的实例,年付通常落在几百元到一千元区间,具体看带宽、地域和是否选 SSD 云盘。
- 人力:配置文件本身不长,熟悉之后半天能上线;真正的投入在中文分词方案选型和增量索引的运维脚本上。
- 隐性成本:索引重建期间的 CPU 与 IO 峰值,以及 ngram 方案带来的磁盘占用增长。
预算敏感的中小站点,现金支出基本只压在服务器上。
国内服务器部署 Sphinx 配置的实操注意点
- 数据库在内网时,
sql_host直接写内网地址,绕公网只会增加延迟。 - 云厂商的安全组要放行 9312 和 9306,也可以只对内网网段开放,别暴露到公网。
- 索引文件放在 SSD 上,重建索引是典型的 IO 密集型操作,机械盘会让重建时间成倍拉长。
- 用 systemd 托管 searchd,别用 nohup,服务单元大致长这样:
[Unit]
Description=Sphinx Search Daemon
After=network.target
[Service]
ExecStart=/usr/bin/searchd --nodetach --config /etc/sphinx/sphinx.conf
ExecStop=/usr/bin/searchd --stopwait --config /etc/sphinx/sphinx.conf
Restart=on-failure
[Install]
WantedBy=multi-user.target
sql_attr_timestamp的时间戳与时区要对齐,否则按时间排序会出现整体偏移。

调优与增量更新:让索引跟得上数据
增量索引的两种思路
- 主索引加增量索引,主索引定期全量重建,增量索引高频重建,再合并回去:
indexer --config /etc/sphinx/sphinx.conf delta --rotate
indexer --config /etc/sphinx/sphinx.conf --merge main delta --rotate
- RT 实时索引,直接放弃批量索引,数据通过 SphinxQL 的 INSERT 写入,binlog 保证进程重启不丢数据,适合更新频繁、对延迟敏感的场景。
几个见效快的参数
max_matches不要设太大,深分页会显著拖慢查询。- 查询用 SphinxQL 的
SHOW META查看耗时,定位慢查询比盲调参数高效得多。 - 排序时用
WEIGHT()拿相关度权重,示例:
SELECT id, title, WEIGHT() AS w
FROM idx_article
WHERE MATCH('全文检索')
ORDER BY w DESC
LIMIT 20;
Sphinx 配置的高频疑问
改了配置一定要重建索引吗
要分情况,改 searchd 段的监听端口、日志路径这类运行参数,重启进程即可生效,改 charset_table、ngram_len、min_word_len 这类影响分词和词典结构的参数,必须执行 indexer --all 全量重建,新旧词典混用会让检索结果错乱。
实时索引和批量索引能同时存在吗
可以,同一份 sphinx.conf 里既能定义 type = rt 的实时索引,也能定义走 source 的普通索引,searchd 启动时会一起加载,查询时用 SphinxQL 对多个索引做联合检索,业务侧再按需合并结果即可。
ngram 和外部词典分词哪个更准
精度和召回本身就是一组权衡,ngram 按固定长度切分,召回率高但精度一般;外部词典分词精度更好,却依赖词典维护和更新频率,业内专家指出,中文搜索没有一劳永逸的切分方案,多数项目最终会走 ngram 兜底、词典增强的组合路线,先在配置层面把两类参数都留出可调空间,再根据实际查询日志迭代。
Sphinx 配置的难点从来不在语法,而在参数之间的联动关系,把 source、index、searchd 三段写清楚,中文分词方案定下来,剩下的工作基本就是围绕内存与磁盘做取舍。


