Sphinx 中文全文搜索引擎
bash
Ubuntu/Debian
sudo apt update sudo apt install -y build-essential libmysqlclient-dev libexpat1-dev
CentOS/RHEL
sudo yum install -y gcc gcc-c++ make mysql-devel expat-devel
---
## 安装与编译 Sphinx
从官网下载 Sphinx 源码包,编译并安装(以 3.3.1 为例):
```bash
wget http://sphinxsearch.com/files/sphinx-3.3.1-3b5c8ad-linux-amd64.tar.gz
tar -xzf sphinx-3.3.1-3b5c8ad-linux-amd64.tar.gz
cd sphinx-3.3.1
# 编译安装
./configure --prefix=/usr/local/sphinx --with-mysql
make
sudo make install
安装完成后,将 /usr/local/sphinx/bin 添加到 PATH:
echo 'export PATH=/usr/local/sphinx/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
集成中文分词器(jieba)
Sphinx 原生不支持中文分词,但可以通过 mmseg 的词典接口加载自定义词库。最简便的方式是使用 sphinx-jieba 扩展。
下载并编译 sphinx-jieba
git clone https://github.com/yanyiwu/sphinx-jieba.git
cd sphinx-jieba
# 修改 Makefile 中的 SPHINX_INC 和 SPHINX_LIB 指向你的 Sphinx 安装路径
make
编译完成后会得到 libsphinx-jieba.so,将其复制到 Sphinx 的插件目录(或其他可加载路径):
sudo cp libsphinx-jieba.so /usr/local/sphinx/lib/
同时需要准备 jieba 的词库文件(dict.txt.big 等),可以从 jieba 官方仓库获取,或者使用你训练好的词库。
配置 Sphinx 数据源与索引
Sphinx 使用配置文件 sphinx.conf 定义数据来源、索引结构和搜索行为。我们创建一个支持中文分词的索引。
示例数据库
假设你的 MySQL 中有一张 articles 表,字段 id, title, content,我们将对 title 和 content 建立全文索引。
CREATE TABLE articles (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255),
content TEXT
);
编写 sphinx.conf
# 数据源定义
source src_articles {
type = mysql
sql_host = localhost
sql_user = root
sql_pass = yourpassword
sql_db = test
sql_port = 3306
sql_query = SELECT id, title, content FROM articles
sql_attr_uint = id
}
# 索引定义
index idx_articles {
source = src_articles
path = /usr/local/sphinx/var/data/idx_articles
docinfo = extern
morphology = none # 不使用内置词干分析
charset_type = utf-8
charset_table = 0..9, A..Z->a..z, _, a..z, \
U+4E00..U+9FFF, \ # 中文字符范围
U+3400..U+4DBF
# 指定自定义分词器
mlock = 0
min_word_len = 1
# 中文分词插件
index_sp = 1
index_field_lengths = 1
# 使用 jieba 分词插件
plugin_dir = /usr/local/sphinx/lib
# 定义 token filter
token_filter = jieba
# jieba 分词器配置
token_filter_jieba {
type = plugin
plugin = libsphinx-jieba.so
# 词库路径
conf = /path/to/jieba/dict/jieba.dict.utf8
hmm = /path/to/jieba/dict/hmm_model.utf8
user = /path/to/jieba/dict/user.dict.utf8
idf = /path/to/jieba/dict/idf.utf8
stop = /path/to/jieba/dict/stop_words.utf8
}
}
# 搜索守护进程
searchd {
listen = 9312
log = /usr/local/sphinx/var/log/searchd.log
query_log = /usr/local/sphinx/var/log/query.log
pid_file = /usr/local/sphinx/var/log/searchd.pid
seamless_rotate = 1
preopen_indexes = 1
unlink_old = 1
workers = threads
}
注意:以上
token_filter_jieba配置在 Sphinx 3.x 中可能需要根据实际插件接口微调。对于旧版 Sphinx 2.x,通常会使用charset_table配合dict方式,或者通过indexer --buildstops生成手工分词。如果你使用的是 Sphinx 2.2.11,可以通过第三方mmseg插件实现分词。
如果你的 Sphinx 版本较旧,可以尝试另一种简单方法:使用外部预处理脚本将中文文本按分词结果用空格分隔,再存储到数据库中,这样 Sphinx 就可以直接使用 charset_table 加上空格分隔的词语进行索引。
索引创建与测试
配置文件写好后,创建索引:
indexer idx_articles --config /usr/local/sphinx/etc/sphinx.conf --rotate
如果索引顺利建完,启动搜索守护进程:
searchd --config /usr/local/sphinx/etc/sphinx.conf
现在可以用 MySQL 客户端或 PHP、Python 等语言连接 Sphinx 进行搜索。Sphinx 的查询接口使用类 SQL 语法,通过 9312 端口。
通过 MySQL 客户端搜索
mysql -h 0 -P 9306
在 SphinxQL 中测试:
SELECT * FROM idx_articles WHERE MATCH('搜索引擎') LIMIT 10;
如果返回相关文章 ID 和权重,说明中文分词和搜索正常工作。
常见问题与优化
1. 分词结果不符合预期
- 检查 jieba 词库路径是否正确,用户自定义词典是否加载。
- 可通过
CALL KEYWORDS('搜索词', 'idx_articles')查看 Sphinx 实际切分出的词条,验证分词效果。
2. 中文短语匹配不精确
- 在 Sphinx 中,默认使用
phrase操作符进行短语搜索:MATCH('"搜索引擎"')会匹配精确顺序的词。 - 调整
min_infix_len参数可以启用中缀匹配,实现部分词匹配,但会显著增加索引大小。
3. 性能调优
- 使用
ondisk_dict启用字典的磁盘存储,节省内存。 - 调整
indexer的内存限制mem_limit。 - 对大型数据集,启用实时索引(RT index)以支持快速增量更新。
4. 实时索引配置示例
如果需要频繁更新数据,使用实时索引更加灵活:
index rt_articles {
type = rt
path = /usr/local/sphinx/var/data/rt_articles
rt_field = title
rt_field = content
rt_attr_uint = id
# 中文分词配置同上
token_filter = jieba
# ... 其他分词设置
}
插入数据:
INSERT INTO rt_articles (id, title, content) VALUES (1, 'Sphinx教程', '这是一个中文全文搜索的详细教程');