sphinx社区全文搜索平台配置手册

合集下载
相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

千万级Discuz!数据全文检索方案(Sphinx)
前言:康盛创想的Discuz!从创立之初即以提高产品效率为突破口,随着编译模板,语法生成内核,数据缓存和自动更新机制等独创或独有技术的应用,和坚固的数据结构及最少化数据库查询设计,使得Discuz! 可以在极为繁忙的服务器环境下快速高效稳定运行。

由于Discuz!产品依赖MySQL数据库性能,在全文检索方面如果仅仅依靠MySQL的LIKE %关键词% 语句无法取得理想的成绩。

本文阐述经过Discuz!生产环境考验的构建在Sphinx基础上的千万级Discuz!数据全文检索解决方案。

出自俄罗斯的开源全文搜索引擎软件Sphinx在单一索引达到4千万条记录情况下的查询速度仍为0.x秒甚至0.0x秒级别。

Sphinx创建索引的速度约五分钟处理百万条记录,对于每分钟的增量索引重建只需要几十秒,每日的增量索引合并到主索引也只需一分钟左右。

此构架基础上的Discuz!高负载站点,已成功解决搜索速度慢、经常锁表、无法分布式搜索等问题。

千万级Discuz!数据全文检索方案(Sphinx)适用于繁忙的站点并且论坛访问者有大量的搜索需求,本方案主要解决搜索缓慢问题。

本文环境以CentOS 5为基准。

初始化一次全部索引,按系统计划任务crontab定时方式,每5分钟重建一次增量索引(增量索引不与主索引合并),每日凌晨3:30建立一次昨日比较的增量索引(合并到主索引中)。

主索引建立在磁盘目录/data/sphdata,增量索引建立在内存/dev/shm/中避免大量的I/O操作,由于帖子编辑限制,全部索引每两个月重建一次。

目录
千万级Discuz!数据全文检索方案(Sphinx) (1)
Sphinx快速介绍 (2)
一、Sphinx全文检索方案构架图 (3)
二、Sphinx中文分词 (4)
三、Sphinx安装步骤 (4)
1.安装、升级所需的程序库 (4)
2.创建安装文件夹并下载源代码 (4)
3.安装MMseg中文分词 (4)
4.安装CSFT(Sphinx的CoreSeek修改版) (5)
5.编译Sphinx过程可能出现的错误 (5)
a)无法找到mysql路径 (5)
b)无法找到libiconv (5)
c)无法找到libmysqlclient.so.15 (5)
d)php 5.2.11版本的api BUG (5)
e)生成索引时容易发生磁盘空间不足写入失败的错误 (5)
6.安装为php扩展(可选) (6)
7.安装SphinxSE存储引擎(可选) (6)
四、Sphinx配置 (6)
1.mmseg中文分词词库 (6)
a)词典格式 (6)
b)词库生成方法 (7)
2.创建sphinx数据目录结构 (7)
3.创建sphinx.conf配置文件 (7)
4.mmseg.ini分词配置文件 (14)
5.建立Sphinx增量索引数据表 (14)
6.书写常用的sphinx控制命令到sh文件 (14)
7.创建相应的文件结构,初始化Sphinx的全部索引 (17)
8.启动sphinx (17)
9.设置计划任务项 (17)
10.设置开机启动项 (17)
五、通过命令行测试搜索 (17)
六、通过php api调用Sphinx搜索 (18)
七、通过MySQL的SphinxSE存储引擎调用Sphinx搜索(可选) (19)
八、Sphinx数据占用量统计 (19)
Sphinx快速介绍
Sphinx是独立的搜索服务端,不依赖MySQL,当Sphinx和MySQL结合部署时,Sphinx的数据来源为MySQL。

服务器安装Sphinx,由sphinx.conf配置文件指定Sphinx的数据源,如何读取MySQL的数据内容,设置Sphinx对MySQL数据库的哪个表哪些字段建立索引,索引的返回数据必须是数值型。

例如一个配置段设置Sphinx对cdb_threads表的subject和author字段建立索引,搜索结果可以返回tid和uid。

另一个配置段设置Sphinx对cdb_posts表的subject和message字段索引,搜索结果返回tid和pid。

Sphinx建立的索引只是查询MySQL数据库获取数据内容,将索引存放在Sphinx的数据文件和内存中,一般不对MySQL数据库进行修改操作。

因为Sphinx独立运行,使用SELECT * FROM cdb_threads WHERE subject LIKE '%关键词%' LIMIT 0, 10;类似的SQL语句将无法利用Sphinx搜索,即使服务器端已经部署Sphinx也不会对该查询语句有任何优化作用。

正确使用Sphinx搜索数据的操作方式主要有三种:
1、命令行的search工具:/usr/local/webserver/sphinx/bin/search –i threads test
2、php的api接口查询:原理是直接用fsockopen连接端口,传递数据取得返回结果。

Sphinx 官方已经提供php的api接口,可以include api查询(本方案以该查询方法为主),也可以将其源代码编译成php扩展而无需include。

3、在mysql中将Sphinx安装为SphinxSE存储引擎,通过SphinxSE方式调用Sphinx。

因Sphinx搜索结果只返回INT类型数据,部署Sphinx搜索的核心是由搜索入口(search.php)提交的关键词到Sphinx中搜索,Sphinx返回对应的tid、pid等信息,再依据tid、pid到cdb_threads 或者cdb_posts中搜索,得到结果集展示在页面上。

Sphinx的搜索速度非常快,而tid/pid都是主键查询,总体来说虽然用了多次查询,但是速度仍
然非常快。

一、Sphinx全文检索方案构架图
二、Sphinx中文分词
打过Sphinx官方补丁的Sphinx可以支持utf8、gbk等编码的汉字,按单个汉字切分,汉语搜索中应以词为依据,独立存在的单个汉字搜索几乎没有意义。

本文介绍的构架方案以CoreSeek的CSFT 修改版为主,由libmmseg对搜索词予以分词切分,Sphinx按切分词建立相应索引从而建立以词和短语为基准的搜索。

三、Sphinx安装步骤
1.安装、升级所需的程序库
yum -y install gcc gcc-c++ autoconf python python-devel libiconv
2.创建安装文件夹并下载源代码
mkdir –p /data/software
cd /data/software
wget /uploads/csft/3.1/Source/mmseg-3.1.tar.gz
wget /uploads/csft/3.1/Source/csft-3.1.tar.gz
3.安装MMseg中文分词
tar -xzf mmseg-3.1.tar.gz
cd mmseg-3.1
./configure --prefix=/usr/local/webserver/mmseg
make
make install
cd ..
4.安装CSFT(Sphinx的CoreSeek修改版)
tar -xzf csft-3.1.tar.gz
cd csft-3.1
./configure --prefix=/usr/local/webserver/csft --with-mmseg=/usr/local/webserver/mmseg/bin/mmseg --with-mmseg-includes=/usr/local/webserver/mmseg/include/mmseg/
--with-mmseg-libs=/usr/local/webserver/mmseg/lib/ --with-mysql=/usr/local/webserver/mysql/
make
make install
cd ..
5.编译Sphinx过程可能出现的错误
a) 无法找到mysql路径
确认–with-mysql=之后的路径正确,是当前mysql所在路径。

如果mysql是通过rpm或者yum 方式安装,直接–with-mysql 使用默认路径即可。

失败尝试指定–with-mysql-includes=路径–with-mysql-libs=路径
b) 无法找到libiconv
libiconv通过yum方式安装的,可以直接识别。

源代码编译安装的,需要建立在/usr/lib和/usr/local/lib下建立相应的软链。

ln –s 源文件目标文件。

或者将libiconv的目录加入到ld.so.conf (例如libiconv安装在/usr/local/lib/目录中)
echo /usr/local/lib/ >> /etc/ld.so.conf
ldconfig
若仍提示libiconv无法找到,需要修改vi src/Makefile 文件,找LIBS = 开头的行,

LIBS = -lm -lz -lexpat -L/usr/local/lib –lpthread
修改成
LIBS = -lm -lz -lexpat -liconv -L/usr/local/lib -lpthread
c) 无法找到libmysqlclient.so.15
将libmysqlclient.so.15建立软链到/usr/local/lib和/usr/lib目录下,或者加入到ld.so.conf
echo /usr/local/webserver/mysql/lib/mysql/ >> /etc/ld.so.conf
ldconfig
d) php 5.2.11版本的api BUG
当站点的php版本为5.2.11,并且通过php api方式获取Sphinx数据,数据超过1000条的情况下有BUG,无法解析正确的数据包。

遇到此情况必须重新编译php版本,目前已知php 5.2.10是与Sphinx API结合非常稳定的版本。

e) 生成索引时容易发生磁盘空间不足写入失败的错误
需要注意配置文件中设置的Sphinx索引数据存放目录,确保有足够的存储空间。

Sphinx的索引
文件占用的空间略小于数据库数据文件本身占用的空间。

6.安装为php扩展(可选)
cd csft-3.1/api/libsphinxclient
CXXCPP="gcc -E" ./configure --prefix=/usr/local/webserver/csft
make
make install
cd ../../
/usr/local/webserver/php/bin/phpize
./configure --with-sphinx=/usr/local/webserver/csft
make
make install
7.安装SphinxSE存储引擎(可选)
安装SphinxSE需要重新编译MySQL,简要介绍另一种搜索方法。

cp -rf csft-3.1/mysqlse mysql-5.1.42/storage/sphinx
cd mysql-5.1.42
sh BUILD/autorun.sh
./configure --prefix=/usr/local/webserver/mysql/ --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-big-tables --with-readline --with-ssl --with-embedded-server --enable-local-infile --with-plugins=sphinx
make && make install
cd ../
四、Sphinx配置
1.mmseg中文分词词库
a) 词典格式
....
河187
x:187
造假者1
x:1
台北队1
x:1
湖边1
......
其中,每条记录分两行。

其中,第一行为词项,其格式为:[词条]\t[词频率]。

需要注意的是,对于单个字后面跟这个字作单字成词的频率,这个频率需要在大量的预先切分好的语料库中进行统计,
用户增加或删除词时,一般不需要修改这个数值;对于非单字词,词频率处必须为1。

第二行为占位项,保持一致即可。

换行符使用\n,字符编码UTF-8
b) 词库生成方法
整理好的文本词库(词条不可重复)new.txt,使用mmseg生成new.txt.uni的二进制词库文件。

/usr/local/webserver/mmseg/bin/mmseg –u new.txt
uni.lib文件存放于/usr/local/webserver/csft目录
mv new.txt.uni /usr/local/webserver/csft/uni.lib
依据社区常见词汇,针对不同行业设计相应的高频词汇,分词将更精确。

uni.lib词库文件发生改变后,sphinx索引需全部重建。

2.创建sphinx数据目录结构
mkdir -p /data/sphdata
mkdir -p /dev/shm/sphminute
3.创建sphinx.conf配置文件
vi /usr/local/webserver/csft/etc/sphinx.conf
#############################################################################
## 数据源
#############################################################################
# Threads
source threads
{
type = mysql
#sphinx从mysql中获取数据源
sql_host = localhost
sql_user = root
sql_pass = test
sql_db = discuz
sql_port = 3306
#sql_sock =/tmp/mysql.sock
#设置mysql数据库帐号密码
sql_query_pre = SET NAMES gbk
sql_query_pre = SET SESSION query_cache_type=OFF
sql_query_pre = REPLACE INTO cdb_sphinxcounter \
SELECT 1, MAX(tid) FROM cdb_threads
#mysql预查询,设置连接字符编码等
sql_query_range = SELECT MIN(tid), (SELECT maxid FROM cdb_sphinxcounter WHERE indexid = 1) FROM cdb_threads
sql_range_step = 1000
#分次查询数据,不要一次将全部数据取出
sql_query = \
SELECT tid, tid as tid, fid, iconid, typeid, sortid, authorid, dateline, displayorder, digest, special, closed, \ subject, \
'threads' AS tablename \
FROM cdb_threads\
WHERE tid>=$start AND tid<=$end
#数据内容包含哪些字段,数据范围是在哪些(通过cdb_sphinxcounter增量表确定数据id范围,不用加读表锁),必须是>= 和<=
sql_attr_uint = tid
sql_attr_uint = fid
sql_attr_uint = iconid
sql_attr_uint = typeid
sql_attr_uint = sortid
sql_attr_uint = authorid
sql_attr_timestamp = dateline
sql_attr_uint = displayorder
sql_attr_uint = digest
sql_attr_uint = special
sql_attr_uint = closed
sql_attr_uint = tablename
#设置返回的数据(返回数据的字段必须是INT类型,可以在Query操作的时候设置过滤器过滤)
sql_query_info = SELECT * FROM `cdb_threads` WHERE tid=$id
}
#分钟处理,只扫描增量,不与主索引合并
source threads_minute: threads
{
sql_query_pre = SET NAMES gbk
sql_query_pre = SET SESSION query_cache_type=OFF
sql_query_pre =
#sql_query_pre的个数应与主索引的个数一致
sql_query_range = SELECT (SELECT maxid FROM cdb_sphinxcounter WHERE indexid = 1), MAX(tid) FROM cdb_threads
sql_range_step = 1000
#限制增量索引只查询主索引中没有的数据(当天新增的数据)
sql_query = \
SELECT tid, tid as tid, fid, iconid, typeid, sortid, authorid, dateline, displayorder, digest, special, closed, \ subject, \
'threads_minute' AS tablename \
FROM cdb_threads\
WHERE tid>=$start AND tid<=$end
}
#每日处理,扫描每日增量,并且与主索引合并
source threads_daily: threads
{
sql_query_pre = SET NAMES gbk
sql_query_pre = SET SESSION query_cache_type=OFF
sql_query_pre =
sql_query_range = SELECT (SELECT maxid FROM cdb_sphinxcounter WHERE indexid = 1), MAX(tid) FROM cdb_threads
sql_range_step = 1000
sql_query = \
SELECT tid, tid as tid, fid, iconid, typeid, sortid, authorid, dateline, displayorder, digest, special, closed, \ subject, \
'threads_daily' AS tablename \
FROM cdb_threads\
WHERE tid>=$start AND tid<=$end
sql_query_post = \
REPLACE INTO cdb_sphinxcounter SELECT 1,MAX(tid) FROM cdb_threads
#获取数据后,改写cdb_sphinxcounter增量索引计数表中的值
}
#threads1为存档的,拆分的历史数据表,如果该站点的Discuz!没有分表,不需要此配置段
source threads1: threads
{
sql_query_pre = SET NAMES gbk
sql_query_pre = SET SESSION query_cache_type=OFF
sql_query_pre =
#sql_query_pre的个数应与主索引的个数一致
sql_query_range = SELECT MIN(tid), MAX(tid) FROM cdb_threads1
sql_range_step = 1000
sql_query = \
SELECT tid, tid as tid, fid, iconid, typeid, sortid, authorid, dateline, displayorder, digest, special, closed, \ subject, \
'threads1' AS tablename \
WHERE tid>=$start AND tid<=$end
}
#设置数据存放信息
index threads
{
source = threads
path = /data/sphdata/threads
docinfo = extern
mlock = 0
morphology = none
min_word_len = 2
charset_type = zh_cn.gbk
charset_dictpath = /usr/local/webserver/csft/
html_strip = 0
}
#每分钟增量数据存放在内存中减少I/O操作
index threads_minute: threads
{
source = threads_minute
path = /dev/shm/sphminute/threads_minute
}
index threads_daily: threads
{
source = threads_daily
path = /data/sphdata/threads_daily
}
#存档分表的数据存放
index threads1: threads
{
source = threads1
path = /data/sphdata/threads1
}
#全文
source posts
{
type = mysql
sql_host = localhost
sql_user = root
sql_pass = test
sql_db = discuz
sql_port = 3306
sql_query_pre = SET NAMES gbk
sql_query_pre = SET SESSION query_cache_type=OFF
sql_query_pre = REPLACE INTO cdb_sphinxcounter SELECT 2, MAX(pid) FROM cdb_posts
sql_query_range = SELECT MIN(pid), (SELECT maxid FROM cdb_sphinxcounter WHERE indexid = 2) FROM cdb_posts
sql_range_step = 500
sql_query = \
SELECT p.pid, p.pid as pid, p.tid, p.fid, p.first, p.invisible, p.authorid, p.dateline, t.iconid, t.typeid, t.sortid, t.displayorder, t.digest, t.special, t.closed, \
p.subject, p.message, \
'posts' AS tablename \
FROM cdb_posts p \
INNER JOIN cdb_threads t ON p.tid = t.tid \
WHERE p.pid>=$start AND p.pid<=$end
sql_attr_uint = pid
sql_attr_uint = tid
sql_attr_uint = fid
sql_attr_uint = first
sql_attr_uint = invisible
sql_attr_uint = authorid
sql_attr_timestamp = dateline
sql_attr_uint = iconid
sql_attr_uint = typeid
sql_attr_uint = sortid
sql_attr_uint = displayorder
sql_attr_uint = digest
sql_attr_uint = special
sql_attr_uint = closed
sql_attr_uint = tablename
sql_query_info = SELECT * FROM `cdb_posts` WHERE pid=$id
}
source posts_minute: posts
{
sql_query_pre = SET NAMES gbk
sql_query_pre = SET SESSION query_cache_type=OFF
sql_query_pre =
sql_query_range = SELECT (SELECT maxid FROM cdb_sphinxcounter WHERE indexid = 2), MAX(pid) FROM cdb_posts
sql_range_step = 500
sql_query = \
SELECT p.pid, p.pid as pid, p.tid, p.fid, p.first, p.invisible, p.authorid, p.dateline, t.iconid, t.typeid, t.sortid, t.displayorder, t.digest, t.special, t.closed, \
p.subject, p.message, \
'posts_minute' AS tablename \
FROM cdb_posts p \
INNER JOIN cdb_threads t ON p.tid = t.tid \
WHERE p.pid>=$start AND p.pid<=$end
}
source posts_daily: posts
{
sql_query_pre = SET NAMES gbk
sql_query_pre = SET SESSION query_cache_type=OFF
sql_query_pre =
sql_query_range = SELECT (SELECT maxid FROM cdb_sphinxcounter WHERE indexid = 2), MAX(pid) FROM cdb_posts
sql_range_step = 500
sql_query = \
SELECT p.pid, p.pid as pid, p.tid, p.fid, p.first, p.invisible, p.authorid, p.dateline, t.iconid, t.typeid, t.sortid, t.displayorder, t.digest, t.special, t.closed, \
p.subject, p.message, \
'posts_daily' AS tablename \
FROM cdb_posts p \
INNER JOIN cdb_threads t ON p.tid = t.tid \
WHERE p.pid>=$start AND p.pid<=$end
sql_query_post = \
REPLACE INTO cdb_sphinxcounter SELECT 2,MAX(pid) FROM cdb_posts
}
#帖子内容数据分表
source posts1: posts
{
sql_query_pre = SET NAMES gbk
sql_query_pre = SET SESSION query_cache_type=OFF
sql_query_pre =
sql_query_range = SELECT MIN(pid), MAX(pid) FROM cdb_posts1
sql_range_step = 500
sql_query = \
SELECT p.pid, p.pid as pid, p.tid, p.fid, p.first, p.invisible, p.authorid, p.dateline, t.iconid, t.typeid, t.sortid, t.displayorder, t.digest, t.special, t.closed, \
p.subject, p.message, \
'posts1' AS tablename \
FROM cdb_posts p \
INNER JOIN cdb_threads t ON p.tid = t.tid \
WHERE p.pid>=$start AND p.pid<=$end
}
index posts
{
source = posts
path = /data/sphdata/posts
docinfo = extern
mlock = 0
morphology = none
min_word_len = 2
charset_type = zh_cn.gbk
charset_dictpath = /usr/local/webserver/csft/
html_strip = 0
}
index posts_minute: posts
{
source = posts_minute
path = /dev/shm/sphminute/posts_minute
}
index posts_daily: posts
{
source = posts_daily
path = /data/sphdata/posts_daily
}
index posts1: posts
{
source = posts1
path = /data/sphdata/posts1
}
#############################################################################
## indexer settings
#############################################################################
indexer
{
mem_limit = 128M
max_iosize = 524288
}
#此处的mem_limit和max_iosize需要配合设置,不能太大影响服务器运行,也不能太小导致sphinx生成索引缓慢。

如果遇到生成索引提前退出而没有任何报错的情况,需适当调小mem_limit设置
#############################################################################
## searchd settings
#############################################################################
searchd
{
listen =3312
#listen = /tmp/searchd.sock
#如果监听为sock方式,注意设置每次启动时设置sock文件的权限为777
log = /usr/local/webserver/csft/var/log/searchd.log
query_log = /usr/local/webserver/csft/var/log/query.log
read_timeout = 10
client_timeout = 10
max_children = 30
pid_file = /var/run/searchd.pid
max_matches = 10000
seamless_rotate = 1
preopen_indexes = 0
unlink_old = 1
mva_updates_pool = 1M
max_packet_size = 16M
max_filters = 256
max_filter_values = 4096
}
4.mmseg.ini分词配置文件
rm –f /usr/local/webserver/csft/mmseg.ini
vi /usr/local/webserver/csft/mmseg.ini
[mmseg]
merge_number_and_ascii=1;
number_and_ascii_joint=-.;
compress_space=0;
seperate_number_ascii=0;
5.建立Sphinx增量索引数据表
CREATE TABLE IF NOT EXISTS `cdb_sphinxcounter` (
`indexid` tinyint(1) NOT NULL,
`maxid` int(10) NOT NULL,
PRIMARY KEY (`indexid`)
) ENGINE=MyISAM DEFAULT CHARSET=gbk;
该表为普通表,区别于SphinxSE存储引擎专用表,该表的数据仅仅是配合Sphinx的增量索引而计数的表,indexid表示索引id,值为1表示threads,值为2表示posts,对应的maxid分别记录了上次sphinx增量索引合并时取得的最大id数。

6.书写常用的sphinx控制命令到sh文件
vi /usr/local/webserver/csft/sph.sh
增加以下内容
#! /bin/sh
#####本shell脚本是将常用的sphinx命令写入到shell中,减少代码量,注意配置部分#####
#####config start#####
sphinx_path=/usr/local/webserver/csft/
sphinx_conf=/usr/local/webserver/csft/etc/sphinx.conf
minute_data_path=/dev/shm/sphminute/
update_indexs=("threads" "posts")
rebuild_indexs=("threads" "posts" "threads1" "posts1" "threads2" "posts2")
#####config end#####
si=0
sj=${#update_indexs[@]}
sk=${#rebuild_indexs[@]}
${sphinx_path}bin/searchd --config $sphinx_conf
#chmod 777 /tmp/searchd.sock
#如果监听为sock方式,注意启动命令设置sock文件权限
}
sph_stop () {
${sphinx_path}bin/searchd --config $sphinx_conf --stop
sleep 3
}
sph_createallindex () {
${sphinx_path}bin/indexer --config $sphinx_conf --all
}
sph_rebuild () {
si=0
while [ "$si" -lt "$sk" ]
do
${sphinx_path}bin/indexer --config $sphinx_conf ${rebuild_indexs[$si]} --rotate
sleep 10
let si=si+1
done
}
sph_minute_create () {
mkdir -p $minute_data_path
si=0
while [ "$si" -lt "$sj" ]
do
${sphinx_path}bin/indexer --config $sphinx_conf ${update_indexs[$si]}_minute
sleep 10
let si=si+1
done
}
sph_minute () {
si=0
while [ "$si" -lt "$sj" ]
do
${sphinx_path}bin/indexer --config $sphinx_conf ${update_indexs[$si]}_minute --rotate sleep 10
let si=si+1
done
}
si=0
while [ "$si" -lt "$sj" ]
do
${sphinx_path}bin/indexer --config $sphinx_conf ${update_indexs[$si]}_daily --rotate && ${sphinx_path}bin/indexer --config $sphinx_conf --merge ${update_indexs[$si]} ${update_indexs[$si]}_daily --rotate sleep 10
let si=si+1
done
}
case "$1" in
start)
sph_start
;;
stop)
sph_stop
;;
restart)
sph_stop
sph_start
;;
minute)
sph_minute
;;
daily)
sph_daily
;;
create)
sph_stop
sph_createallindex
sph_start
;;
minute_create)
sph_minute_create
sph_start
;;
rebuild)
sph_rebuild
;;
*)
echo "Usage: $0 {start|stop|restart|minute|daily|create|minute_create|rebuild}"
exit 1
;;
esac
编辑完后,设置可执行权限
chmod +x /usr/local/webserver/csft/sph.sh
shell使用举例:
/usr/local/webserver/csft/sph.sh start #启动sphinx的searchd守护进程
/usr/local/webserver/csft/sph.sh stop #停止sphinx的searchd守护进程
7.创建相应的文件结构,初始化Sphinx的全部索引
mkdir –p /data/sphdata/
/usr/local/webserver/csft/sph.sh creat
此过程耗时比较长,可以配合screen进入无人值守模式防止中断,适当调整indexer配置段中的内存和I/O占用量,避开高峰时期建立索引,以免出现服务器无法响应问题。

8.启动sphinx
/usr/local/webserver/csft/sph.sh start
9.设置计划任务项
crontab –e
增加以下内容
###sphinx增量索引,每5分钟重建一次增量索引,资源消耗少(4、5点之间是每15分钟重建一次增量索引)
*/5 0-2 * * * /usr/local/webserver/csft/sph.sh minute
*/15 4,5 * * * /usr/local/webserver/csft/sph.sh minute
*/5 6-23 * * * /usr/local/webserver/csft/sph.sh minute
###sphinx每天03:30将增量索引与主索引合并,合并耗时约10分钟
30 3 * * * /usr/local/webserver/csft/sph.sh daily
###sphinx适当的时机需要重新建立全部索引,耗时约1小时,例如每两个月
### /usr/local/webserver/csft/sph.sh rebuild
10.设置开机启动项
vi /etc/rc.d/rc.local
增加以下内容
#/dev/shm是内存信息,重启将会导致文件结构丢失,所以开机初始化一次增量数据并启动sphinx
/usr/local/webserver/csft/sph.sh minute_creat
五、通过命令行测试搜索
/usr/local/webserver/csft/bin/search --config /usr/local/webserver/csft/etc/sphinx.conf -i threads 康盛创想-i 表示指定使用哪个索引搜索,--config 指定使用配置文件,本利中使用threads帖子标题索引搜索。

最末尾的搜索关键词符合sphinx Query语法规则。

屏幕回显以下信息
六、通过php api调用Sphinx搜索
search.php依据提交的关键词,拼凑出相应的Sphinx Query语句,返回帖子id存放于$result 数组,然后数据库主键查询SELECT * FROM cdb_threads WHERE tid IN($result);返回对应的数据结果。

php调用Sphinx搜索示例:
<?php
/*包含sphinx安装目录下的shpinxapi.php文件*/
include('api/sphinxapi.php');
$result = $fids = array();
$s = new SphinxClient();
$s->SetServer('localhost', 3312); //连接Sphinx的服务器端口
$s->SetMatchMode(SPH_MATCH_EXTENDED); //匹配模式,默认为SPH_MATCH_ALL,将Query输入当作普通词汇,并且匹配所有词汇
$result = $s->Query('康盛创想Discuz', 'threads, threads_minute'); //传递Query语句到Sphinx搜索,获得结果存放于$result数组。

如果匹配模式为SPH_MATCH_EXTENDED,则可以使用Query语法。

if($result === false) {
echo 'Query failed:'.$s->GetLastError()."\n";
} elseif(!empty($result['matches']) && is_array($result['matches'])) {
foreach($result['matches'] as $doc=>$docinfo) {
if($docinfo['attrs']['tid']) {
$tids[$docinfo['attrs']['tid']] = $docinfo['attrs']['tid'];
}
}
echo '<pre>';
print_r($result); //Sphinx原始的查询返回数据
print_r($fids); //经整理过的fids数组
//$db->query("SELECT * FROM cdb_threads WHERE fid IN ($fids)"); //依据fids再查询数据库,得到结果集显示
//while($thread = $db->fetch_array($query)) {
//print_r($thread);
//}
echo '</pre>';
} else {
echo 'Error';
}
>
七、通过MySQL的SphinxSE存储引擎调用Sphinx搜索(可选)
本文主要阐述Sphinx API搜索方法,同时也提供SphinxSE搜索方法参考。

首先要建立一个Sphinx索引专用表
CREATE TABLE`sphinx`(
`id`int(11)NOT NULL,
`weight`int(11)NOT NULL,
`query`varchar(255)NOT NULL,
`CATALOGID`INT NOT NULL,
`EDITUSERID`INT NOT NULL,
`HITS`INT NULL,
`ADDTIME`INT NOT NULL, KEY
`Query`(`Query`)
)ENGINE=SPHINX DEFAULT CHARSET=utf8CONNECTION='sphinx://localhost:3312/test1'全文搜索部分只需要SQL语句做相应更改,写成多表联合查询的方法。

例如:
SELECT t.* FROM cdb_threads t INNER JOIN sphinx s ON t.tid=s.id WHERE s.Query = 'Discuz 康盛创想; mod=EXTENDED';
八、Sphinx数据占用量统计
Sphinx占用的数据空间与MySQL数据量大致是1:0.7。

相关文档
最新文档