1.为什么要使用Sphinx
假设你现在运营着一个论坛,论坛数据已经超过100+W,很多用户都反映论坛搜索的速度非常慢,那么这时你就可以考虑使用Sphinx了(当然其他的全文检索程序或方法也行)。
2.Sphinx是什么
Sphinx由俄罗斯人AndrewAksyonoff开发的高性能全文搜索软件包,在GPL与商业协议双许可协议下发行。
全文检索是指以文档的全部文本信息作为检索对象的一种信息检索技术。检索的对象有可能是文章的标题,也有可能是文章的作者,也有可能是文章摘要或内容。
3.Sphinx的特性
l高速索引(在新款CPU上,接近10MB/秒);
l高速搜索(2-4G的文本量中平均查询速度小于0.1秒);
l高可用性(单CPU上最大可支持100GB的文本,100M文档);
l提供良好的相关性排名
l支持分布式搜索;
l提供文档摘要生成;
l提供从MySQL内部的插件式存储引擎上搜索
l支持布尔,短语,和近义词查询;
l支持每个文档多个全文检索域(默认最大32个);
l支持每个文档多属性;
l支持断词;
l支持单字节编码与UTF-8编码;
4.下载并安装Sphinx
打开网址/news/7/52/找到适合自己的操作系统的版本,比如我是Windows那么我就可以下载CoreseekWin32通用版本,Linux下可以下载源码包,自己编译安装。这里解释下为什么我们下载的程序叫Coreseek,Coreseek是基于Sphinx开发的一款软件,对Sphinx做了一些改动,在中文方面支持得比Sphinx好,所以我们使用之。
下载完成后,将程序解压到你想解压的地方,比如我就想解压到E盘根目录,之后修改目录名为Coreseek,大功告成Coreseek安装完成了,安装的目录是在E:\coreseek\。
5.使用Sphinx
我要使用Sphinx需要做以下几件事
1)首先得有数据
2)建立Sphinx配置文件
3)生成索引
4)启动Sphinx
5)使用之(调用api或search.exe程序进行查询)
第1件:(导入数据)
我们建立测试所需要用到得数据库、表以及数据,篇幅有限,这些在附件中都有,下载后导入MySQL即可。
第2件:(建立配置文件)
接下来我们需要建立一个Sphinx的配置文件E:\coreseek\etc\mysql.conf,将其内容改为下面这些:
sourcemysql{
type=mysql
sql_host=localhost
sql_user=root
sql_pass=
sql_db=test
sql_port=3306
sql_query_pre=SETNAMESutf8
sql_query=SELECTid,addtime,title,contentFROMpost
sql_attr_timestamp=addtime
}
indexmysql{
source=mysql
path=E:/coreseek/var/data/mysql
charset_dictpath=E:/coreseek/etc/
charset_type=zh_cn.utf-8
}
searchd{
listen=9312
max_matches=1000
pid_file=E:/coreseek/var/log/searchd_mysql.pid
log=E:/coreseek/var/log/searchd_mysql.log
query_log=E:/coreseek/var/log/query_mysql.log
}
先讲下这个配置文件中每项的含义。
sourcemysql{}定义源名称为mysql,也可以叫其他的,比如:sourcexxx{}
type数据源类型
sql_*数据相关的配置,比如sql_host,sql_pass什么的,这些不解释。(数据源的配置信息)
sql_query建立索引时的查询命令,在这里尽可能不使用where或groupby,将where与groupby的内容交给sphinx,由sphinx进行条件过滤与groupby效率会更高,注意:select的字段必须包括一个唯一主键以及要全文检索的字段,where中要用到的字段也要select出来
sql_query_pre在执行sql_query前执行的sql命令,可以有多条 。
sql_attr以这个开头的配置项,表示属性字段,在where,orderby,groupby中出现的字段要分别定义一个属性,定义不同类型的字段要用不同的属性名,比如上面的sql_attr_timestamp就是时间戳类型。
indexmysql{}定义索引名称为mysql,也可以叫其他的,比如:indexxxx{}
source关联源,就是sourcexxx定义的。
path索引文件存放路径,比如:E:/coreseek/var/data/mysql实际存放在E:/coreseek/var/data/目录,然后创建多个名称为mysql后缀却不同的索引文件
charset_dictpath指明分词法读取词典文件的位置,当启用分词法时,为必填项。在使用LibMMSeg作为分词库时,需要确保词典文件uni.lib在指定的目录下
charset_type字符集,比如charset_type=zh_cn.gbk
searchd{}sphinx守护进程配置
listen监听端口
max_matches最大匹配数,也就是查找的数据再多也只返回这里设置的1000条
pid_filepid文件路径
log全文检索日志
query_log查询日志
好了,配置文件就这样,配置的参数还有很多,大家可以自己查文档。
第3件:(生成索引)
开始->运行->输入cmd回车,打开命令行工具
e:\coreseek\bin\indexer--confige:\coreseek\etc\mysql.conf--all
这一串东西其实就是调用indexer程序来生成所有索引
如果只想对某个数据源进行索引,则可以这样:e:\coreseek\bin\indexer--confige:\coreseek\etc\mysql.conf索引名称(索引名称指配置文件中所定义的)
--config,--all这些都是indexer程序的参数,想了解更多参数的朋友可以查看文档
运行命令后如果你没看到FATAL,ERROR这些东西,那么索引文件就算生成成功了,比如我看到得就是
………省略………
usingconfigfile'e:\coreseek\etc\mysql.conf'...
indexingindex'mysql'...
collected4docs,0.0MB
………省略………
第4件:(启动Sphinx)
同样命令行下
e:\coreseek\bin\searchd--confige:\coreseek\etc\mysql.conf
运行后提示了一大堆东西
usingconfigfile'e:\coreseek\etc\mysql.conf'...
listeningonallinterfaces,port=9312
acceptingconnections
这样Sphinx是启动好了。
现在有一串鸟文的这个命令行是不能关的,因为关了Sphinx也就关了,如果觉得这样不爽,可以将Sphinx安装成系统服务,在后台运行。
安装系统服务只需在命令行中输入以下命令
e:\coreseek\bin\searchd--confige:\coreseek\etc\mysql.conf--install
安装之后记得启动这个服务,不会启动那我没法,自己google、360 so。
第5步:(使用Sphinx)
在web根目录下建立一个search目录(当然不在根目录也行,同样目录名也可以随取),复制E:\coreseek\api\sphinxapi.php文件到search目录(sphinxapi.php这个是sphinx官方提供的api),开始php程序的编写。
在search目录建立一个文件,名字叫啥都行,我管它叫index.php,其内容如下<?php
include'sphinxapi.php';//加载SphinxAPI
$sc=newSphinxClient();//实例化Api
$sc->setServer('localhost',9312);//设置服务端,第一个参数sphinx服务器地址,第二个sphinx监听端口
$res=$sc->query('sphinx','mysql');//执行查询,第一个参数查询的关键字,第二个查询的索引名称,mysql索引名称(这个也是在配置文件中定义的),多个索引名称以,分开,也可以用*表示所有索引。
print_r($res);
打印结果:Array
(
………省略………
[matches]=>Array(
[2]=>Array(
[weight]=>2
[attrs]=>Array
(
[addtime]=>128262
)
)
[4]=>Array
(
[weight]=>2
[attrs]=>Array
(
[addtime]=>1282622079
)
)
)
………省略………
)
Matches中就是查询的结果了,但是仿佛不是我们想要的数据,比如titile,content字段的内容就没有查询出来,根据官方的说明是Sphinx并没有连接到MySQL去取数据,只是根据它自己的索引内容进行计算,因此如果想用Sphinx提供的API去取得我们想要的数据,还必须以查询的结果为依据,再次查询MySQL从而得到我们想要的数据。
查询结果中键值分别表示
2唯一主键
weight权重
attrssql_attr_*中配置
至此,搜索引擎算是完成一大半了,剩下的大家可以自行完成。
比如:<?php
$ids=array_keys($res['matches']);//获取主键
$ids=join(',',$ids);
$query=mysql_query("SELECT*FROMpostWHEREidIN({$ids})");
while($row=mysql_fetch_assoc($query)){
.....}
Sphinx在windows下安装使用
前一阵子尝试使用了一下Sphinx,一个能够被各种语言(PHP/Python/Ruby/etc)方便调用的全文检索系统。网上的资料大多是在linux环境下的安装使用,当然,作为生产环境很有必要部署在*nix环境下,作为学习测试,还是windows环境比较方便些。
本文旨在提供一种便捷的方式让Sphinx在windows下安装配置以支持中文全文检索,配置部分在linux下通用。
一、关于Sphinx
Sphinx是一个在GPLv2下发布的一个全文检索引擎,商业授权(例如,嵌入到其他程序中)需要联系作者()以获得商业授权。
一般而言,Sphinx是一个独立的搜索引擎,意图为其他应用提供高速、低空间占用、高结果相关度的全文搜索功能。Sphinx可以非常容易的与SQL数据库和脚本语言集成。
当前系统内置MySQL和PostgreSQL数据库数据源的支持,也支持从标准输入读取特定格式的XML数据。通过修改源代码,用户可以自行增加新的数据源(例如:其他类型的DBMS的原生支持)。
搜索API支持PHP、Python、Perl、Rudy和Java,并且也可以用作MySQL存储引擎。搜索API非常简单,可以在若干个小时之内移植到新的语言上。Sphinx特性:
高速的建立索引(在当代CPU上,峰值性能可达到10MB/秒);
高性能的搜索(在2–4GB的文本数据上,平均每次检索响应时间小于0.1秒);可处理海量数据(目前已知可以处理超过100GB的文本数据,在单一CPU的系统上可处理100M文档);
提供了优秀的相关度算法,基于短语相似度和统计(BM25)的复合Ranking方法;支持分布式搜索;
提供文件的摘录生成;
可作为MySQL的存储引擎提供搜索服务;
支持布尔、短语、词语相似度等多种检索模式;文档支持多个全文检索字段(最大不超过32个);
文档支持多个额外的属性信息(例如:分组信息,时间戳等);停止词查询;
支持单一字节编码和UTF-8编码;
原生的MySQL支持(同时支持MyISAM和InnoDB);
原生的PostgreSQL支持.
中文手册可以在这里获得(酷勤网备用下载地址:sphinx_doc_zhcn_0.9.pdf )。
二、Sphinx在windows上的安装
1.直接在/downloads.html找到最新的windows版本,我这里下的是Win32releasebinarieswithMySQLsupport,下载后解压在D:\sphinx目录下;
2.在D:\sphinx\下新建一个data目录用来存放索引文件,一个log目录方日志文件,复制D:\sphinx\sphinx.conf.in到D:\sphinx\bin\sphinx.conf(注意修改文件名);
3.修改D:\sphinx\bin\sphinx.conf,我这里列出需要修改的几个:
type=mysql#数据源,我这里是mysqlsql_host=localhost#数据库服务器sql_user=root#数据库用户名sql_pass=''#数据库密码sql_db=test#数据库
sql_port=3306#数据库端口
sql_query_pre=SETNAMESutf8#去掉此行前面的注释,如果你的数据库是uft8编码的indextest1{
#放索引的目录
path=D:/sphinx/data/#编码
charset_type=utf-8#指定utf-8的编码表
charset_table=0..9,A..Z->a..z,_,a..z,U+410..U+42F->U+430..U+44F,U+430..U+44F
#简单分词,只支持0和1,如果要搜索中文,请指定为1ngram_len=1
#需要分词的字符,如果要搜索中文,去掉前面的注释ngram_chars=U+3000..U+2FA1F}
#indextest1stemmed:test1#{
#path=@CONFDIR@/data/test1stemmed#morphology=stem_en#
}
如果没有分布式索引,注释掉下面的内容
#indexdist1#{
#'distributed'indextypeMUSTbespecified#type=distributed#localindextobesearched
#therecanbemanylocalindexesconfigured#local=test1
#local=test1stemmed#remoteagent
#multipleremoteagentsmaybespecified
#syntaxis'hostname:port:index1,[index2[,...]]#agent=localhost:3313:remote1
#agent=localhost:3314:remote2,remote3
#remoteagentconnectiontimeout,milliseconds#optional,defaultis1000ms,ie.1sec#agent_connect_timeout=1000
#remoteagentquerytimeout,milliseconds#optional,defaultis3000ms,ie.3sec#agent_query_timeout=3000#}
#搜索服务需要修改的部分searchd{
#日志
log=D:/sphinx/log/searchd.log#PIDfile,searchdprocessIDfilenamepid_file=D:/sphinx/log/searchd.pid#windows下启动searchd服务一定要注释掉这个#seamless_rotate=1}
4.导入测试数据
sql文件在D:/sphinx/example.sqlC:\ProgramFiles\MySQL\MySQLServer
5.0\bin>mysql
-uroot
test
5.建立索引
D:\sphinx\bin>indexer.exetest1(备注:test1为sphinx.conf的indextest1())
Sphinx0.9.8-release(r1533)
Copyright(c)2001-,AndrewAksyonoff
usingconfigfile‘./sphinx.conf’…indexingindex‘test1′…collected4docs,0.0MB
sorted0.0Mhits,100.0%donetotal4docs,193bytes
total0.101sec,1916.30bytes/sec,39.72docs/secD:\sphinx\bin>
6.搜索’test’试试
D:\sphinx\bin>search.exetest1Sphinx0.9.8-release(r1533)
Copyright(c)2001-,AndrewAksyonoff
usingconfigfile‘./sphinx.conf’…
index‘test1′:query‘test‘:returned3matchesof3totalin0.000sec
displayingmatches:
1.document=1,weight=2,group_id=1,date_added=WedNov2614:58:59id=1
group_id=1group_id2=5
date_added=-11-2614:58:59title=testone
content=thisismytestdocumentnumberone.alsocheckingsearchwithinphrases.
2.document=2,weight=2,group_id=1,date_added=WedNov2614:58:59id=2
group_id=1group_id2=6
date_added=-11-2614:58:59title=testtwo
content=thisismytestdocumentnumbertwo
3.document=4,weight=1,group_id=2,date_added=WedNov2614:58:59id=4
group_id=2group_id2=8
date_added=-11-2614:58:59title=docnumberfour
content=thisistotestgroups
words:
1.‘test’:3documents,5hitsD:\sphinx\bin>都所出来了吧。6.测试中文搜索
修改test数据库中documents数据表,
UPDATE`test`.`documents`SET`title`=‘测试中文’,`content`=‘thisismytestdocumentnumbertwo,应该搜的到吧’WHERE`documents`.`id`=2;
重建索引:
D:\sphinx\bin>indexer.exetest1搜索’中文’试试:
D:\sphinx\bin>search.exe中文Sphinx0.9.8-release(r1533)
Copyright(c)2001-,AndrewAksyonoff
usingconfigfile‘./sphinx.conf’…
index‘test1′:query‘中文‘:returned0matchesof0totalin0.000sec
words:
D:\sphinx\bin>
貌似没有搜到,这是因为windows命令行中的编码是gbk,当然搜不出来。我们可以用程序试试,在D:\sphinx\api下新建一个foo.php的文件,注意utf-8编码
require’sphinxapi.php’;$s=newSphinxClient();
$s->SetServer(’localhost’,9312);$result=$s->Query(’中文’);var_dump($result);?>
启动Sphinxsearchd服务
D:\sphinx\bin>searchd.exeSphinx0.9.8-release(r1533)
Copyright(c)2001-,AndrewAksyonoffWARNING:forcing–consolemodeonWindowsusingconfigfile‘./sphinx.conf’…creatingserversocketon0.0.0.0:9312acceptingconnections
已经表示服务器已经开启不要关闭命令行(目前本人无法将此服务安装成系统服务器所以每次PHP测试前注意开启searchd服务)执行PHP查询:
访问/sphinx/api/foo.php(自己配置的虚拟主机)
结果是不是出来?剩下的工作就是去看手册,慢慢摸索高阶的配置。
Windows下的Sphinx+MySQL简单配置及调试01月15日星期五02:44P.M.
首先我们要从Sphinx官网上/downloads.html下载mysql-5.0.45-sphinxse-0.9.8-win32.zip和
sphinx-0.9.8.1-win32.zip,假设你已经安装好了MySQL
先将mysql服务停掉解压mysql-5.0.45-sphinxse-0.9.8-win32.zip将bin和share覆盖掉mysql目录中的bin和share解压
sphinx-0.9.8.1-win32.zip到独立的目录,如:d:/www/sphinx/中接着开启mysql服务,建立"test"数据库,并导入sql语句,如下:
-----------------------------------------------------------
CREATETABLE`documents`(
`id`int(11)NOTNULLauto_increment,`group_id`int(11)NOTNULL,`group_id2`int(11)NOTNULL,`date_added`datetimeNOTNULL,`title`varchar(255)NOTNULL,`content`textNOTNULL,PRIMARYKEY(`id`)
)ENGINE=InnoDBAUTO_INCREMENT=5;
INSERTINTO`documents`VALUES('1','1','5','-09-1321:37:47','testone','thisismytestdocumentnumberone.alsocheckingsearchwithinphrases.');
INSERTINTO`documents`VALUES('2','1','6','-09-1321:37:47','testtwo','thisismytestdocumentnumbertwo');
INSERTINTO`documents`VALUES('3','2','7','-09-1321:37:47','anotherdoc','thisisanothergroup');
INSERTINTO`documents`VALUES('4','2','8','-09-1321:37:47','docnumberfour','thisistotestgroups');
-------------------------------------------实际上,这个新建立的表就是Sphinx中的example.sql
我们的测试表已经建立完成,接下来我们要配置sphinx-doc.conf文件(重要)先将sphinx下的sphinx-min.conf复制一份改名为sphinx-doc.conf,接着修改它:
--------------------------------------------------------------------
#
#MinimalSphinxconfigurationsample(clean,simple,functional)#
#type----------------------------------------数据库类型,目前支持mysql与pgsql
#strip_html--------------------------------是否去掉html标签
#sql_host----------------------------------数据库主机地址
#sql_user----------------------------------数据库用户名
#sql_pass----------------------------------数据库密码
#sql_db-------------------------------------数据库名称
#sql_port-----------------------------------数据库采用的端口
#sql_query_pre--------------------------执行sql前要设置的字符集,用utf8必须SETNAMESutf8
#sql_query---------------------------------全文检索要显示的内容,在这里尽可能不使用where或groupby,将where与groupby的内容交给sphinx,由sphinx进行条件过滤与groupby效率会更高
#注意:select出来的字段必须至少包括一个唯一主键(ARTICLESID)以及要全文检索的字段,你计划原本在where中要用到的字段也要select出来#这里不用使用orderby
#sql_attr_开头的表示一些属性字段,你原计划要用在where,orderby,groupby中的字段要在这里定义(#为自己添加的注释内容)
#source数据源名:
sourcedocuments{
type=mysqlsql_host=localhostsql_user=root
sql_pass=yourpasswordsql_db=test
sql_port=3306#optional,defaultis3306
sql_query_pre=SETNAMESutf8sql_query=\
SELECTid,group_id,UNIX_TIMESTAMP(date_added)ASdate_added,title,content\FROMdocuments
sql_attr_uint=group_id
sql_attr_timestamp=date_added
sql_query_info=SELECT*FROMdocumentsWHEREid=$id}
indexdocuments{
source=documents
#path索引记录存放目录,如d:/sphinx/data/cgfinal,实际存放时会存放在d:/sphinx/data目录,然后创建多个cgfinal名称,不同扩展名的索引文件。
path=d:/www/sphinx/data/docdocinfo=externenable_star=1
min_word_len=3min_prefix_len=0min_infix_len=3charset_type=sbcs
#其他的配置如min_word_len,charset_type,charset_table,ngrams_chars,ngram_len这些则是支持中文检索需要设置的内容。
#如果检索的不是中文,则charset_table,ngrams_chars,min_word_len就要设置不同的内容,具体官方网站的论坛中有很多,大家可以去搜索看看。
}
#mem_limit索引使用内存最大限制,根据机器情况而定,默认是32M,太小的会影响索引的性能。indexer{
mem_limit=32M}
#搜索的守护进程配置
#在进行全文检索过程中,searchd要先开启,mysql在全文检索时才能连接到sphinx,由sphinx进行全文检索,再将结果返回给mysql#address侦听请求的地址,不设置则侦听所有地址#port侦听端口searchd{
port=3312
log=d:/www/sphinx/logs/searched_doc.log
query_log=d:/www/sphinx/logs/query_doc.log
read_timeout=5
max_children=30
pid_file=d:/www/sphinx/logs/searched-doc.pid
max_matches=1000
seamless_rotate=0
preopen_indexes=0
unlink_old=1
}
--------------------------------------------------------------------
为了测试,我们的Sphinx配置文件已经写好,确保我们的Mysql数据库已经启动,如果没有启动则在cmd中键入"netstartmysql"接下来,我们的测试正式开始:1,生成数据索引或重建索引:
(最好再复制一个sphinx-doc.conf配置文件,并把它放入bin文件夹中,下面的举例假设我们已经这样做):在cmd模式下:输入:
d:/www/sphinx/bin/indexer.exe--config
d:/www/sphinx/bin/sphinx-doc.confdocuments2,运行检索守护进程searchd.exe:d:/www/sphinx/bin/searchd.exe--configd:/www/sphinx/bin/sphinx-doc.conf
如过这两步没有报错的话,说明我们的Sphinx已经正常运行了!可以通过netstat-an查看是否3312端口是否处如监听状态。3,现在来用sphinx自带的工具search.exe来测试一下:
测试:
索引关键字:thisism
D:\www\sphinx\bin>search.exe-cd:/www/sphinx/bin/sphinx-doc.confthisism结果:
Sphinx0.9.8-release(r1371)
Copyright(c)2001-,AndrewAksyonoff
usingconfigfile'd:/www/sphinx/bin/sphinx-doc.conf'...
WARNING:index'documents':invalidmorphologyoption'extern'-IGNOREDindex'documents':query'thisism':returned4matchesof4totalin0.000sc
displayingmatches:
1.document=1,weight=1,group_id=1,date_added=SatSep1321:37:47id=1
group_id=1group_id2=5
date_added=-09-1321:37:47title=testonecontent=thisismytestdocumentnumberone.alsocheckingsearchwithiphrases.
2.document=2,weight=1,group_id=1,date_added=SatSep1321:37:47id=2
group_id=1group_id2=6
date_added=-09-1321:37:47title=testtwo
content=thisismytestdocumentnumbertwo
3.document=3,weight=1,group_id=2,date_added=SatSep1321:37:47id=3
group_id=2group_id2=7
date_added=-09-1321:37:47title=anotherdoc
content=thisisanothergroup
4.document=4,weight=1,group_id=2,date_added=SatSep1321:37:47id=4
group_id=2group_id2=8
date_added=-09-1321:37:47title=docnumberfour
content=thisistotestgroupswords:
1.'this':4documents,4hits
索引关键字:thisisanothergroup
D:\www\sphinx\bin>search.exe-cd:/www/sphinx/bin/sphinx-doc.confthisisanothergroup结果:
Sphinx0.9.8-release(r1371)
Copyright(c)2001-,AndrewAksyonoff-------------------
到此sphinx在win上算正常运行了,sphinx-doc.conf文件配置比较灵活,根据你需要索引的数据库进行灵活配置来达到你需要的效果
如果配置过程中出现运行参数配置问题可以查看doc/sphinx.html文件,里面对各种参数都要详细的说明
usingconfigfile'd:/www/sphinx/bin/sphinx-doc.conf'...
WARNING:index'documents':invalidmorphologyoption'extern'-IGNOREDindex'documents':query'thisisanothergroup':returned1matchesof1totalin0.000sec
displayingmatches:
1.document=3,weight=4,group_id=2,date_added=SatSep1321:37:47id=3
group_id=2group_id2=7
date_added=-09-1321:37:47title=anotherdoc
content=thisisanothergroupwords:
1.'this':4documents,4hits2.'another':1documents,2hits3.'group':1documents,1hits