sphinx+MySQL+sphinxse+mmseg

Sphinx+MySQL5.1x+SphinxSE+mmseg中文分词

搜索引擎架构搭建手记

什么是Sphinx

Sphinx是一个全文检索引擎,一般而言,Sphinx是一个独立的搜索引擎,意图为其他应用提供高速、低空间占用、高结果相关度的全文搜索功能。Sphinx可以非常容易的与SQL数据库和脚本语言集成。当前系统内置MySQL和PostgreSQL数据库数据源的支持,也支持从标准输入读取特定格式的XML数据。通过修改源代码,用户可以自行增加新的数据源(例如:其他类型的DBMS的原生支持)。

Sphinx的特性

 高速的建立索引(在当代CPU上,峰值性能可达到10 MB/秒);

 高性能的搜索(在2–4GB的文本数据上,平均每次检索响应时间小于0.1秒);

 可处理海量数据(目前已知可以处理超过100 GB的文本数据,在单一CPU的系统上可处理100 M文档);

 提供了优秀的相关度算法,基于短语相似度和统计(BM25)的复合Ranking方法;支持分布式搜索;

provides documentexceprts generation;

 可作为MySQL的存储引擎提供搜索服务;

 支持布尔、短语、词语相似度等多种检索模式;

 文档支持多个全文检索字段(最大不超过32个);

 文档支持多个额外的属性信息(例如:分组信息,时间戳等);

 停止词查询;

 支持单一字节编码和UTF-8编码;

 原生的MySQL支持(同时支持MyISAM和InnoDB);

原生的PostgreSQL支持.

安装

本文以CentOS5.5+mysql-5.1.55+sphinx-0.9.9(coreseek-3.2.14.tar.gz)为例介绍

Sphinx+MySQL5.1x+SphinxSE存储引擎+mmseg中文分词搜索引擎架构搭建过程。

1.安装MySQL+SphinxSE,进入软件包目录

tar zxvfmysql-5.1.55.tar.gz

tar zxvfsphinx-0.9.9.tar.gz

cp -rsphinx-0.9.9/mysqlse/ mysql-5.1.55/storage/sphinxà把sphinx的源代码复制到mysql源码中

cdmysql-5.1.55

./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=partition,innobase,myisammrg,sphinx

make

make install

#/usr/sbin/groupadd mysql

#/usr/sbin/useradd -g mysql mysql

# chmod +w/usr/local/webserver/mysql

# chown -Rmysql:mysql /usr/local/webserver/mysql

①、创建MySQL数据库存放目录

#---------------------------------+

# mkdir -p /data0/mysql/3306/data/

# chown -Rmysql:mysql /data0/mysql/

#---------------------------------+

②、以mysql用户帐号的身份建立数据表:

#---------------------------------+

#/usr/local/webserver/mysql/bin/mysql_install_db--basedir=/usr/local/webserver/mysql --datadir=/data0/mysql/3306/data--user=mysql

#---------------------------------+

③、创建my.cnf配置文件:

#--------------------------------+

# vi /data0/mysql/3306/my.cnf

#--------------------------------+

my.cnf输入以下内容:

[client]

default-character-set= utf8

port = 3306

socket =/tmp/mysql.sock

[mysql]

no-auto-rehash

[mysqld]

user = mysql

port = 3306

socket =/tmp/mysql.sock

basedir =/usr/local/webserver/mysql

datadir =/data0/mysql/3306/data

open_files_limit= 10240

back_log = 600

max_connections= 3000

max_connect_errors= 6000

table_cache =614

external=locking= FALSE

max_allowed_packet= 32M

sort_buffer_size= 2M

join_buffer_size= 2M

thread_cache_size= 300

thread_concurrency= 8

query_cache_size= 32M

query_cache_limit= 2M

query_cache_min_res_unit= 2k

default-storage-engine= MyISAM

default_table_type= MyISAM

thread_stack =192K

transaction_isolation= READ-COMMITTED

tmp_table_size= 246M

max_heap_table_size= 246M

long_query_time= 1

log_long_format

log-bin = /data0/mysql/3306/binlog

binlog_cache_size = 4M

binlog_format= MIXED

max_binlog_cache_size= 8M

max_binlog_size= 512M

expire_logs_days= 7

key_buffer_size= 256M

read_buffer_size= 1M

read_rnd_buffer_size= 16M

bulk_insert_buffer_size= 64M

myisam_sort_buffer_size= 128M

myisam_max_sort_file_size= 10G

myisam_repair_threads= 1

myisam_recover

skip-name-resolve

master-connect-retry= 10

slave-skip-errors= 1032,1062,126,1114,1146,1048,1396

server-id = 1

[mysqldump]

quick

max_allowed_packet= 32M

#--------------------------------开启MYSQL:---------------+

/usr/local/webserver/mysql/bin/mysqld_safe--defaults-file=/data0/mysql/3306/my.cnf 2>&1 > /dev/null &

#-----------------------------------------------------------+

#--------------------------------关闭MYSQL:---------------+

/usr/local/webserver/mysql/bin/mysqladmin-u root -p -S /tmp/mysql.sock shutdown

#-----------------------------------------------------------+

⑦、通过命令行登录管理MySQL服务器(提示输入密码时直接回车):

#----------------------------------------------------------------+

#/usr/local/webserver/mysql/bin/mysql -u root -p -S /tmp/mysql.sock

#----------------------------------------------------------------+

安装完成启动MySQL后查看sphinx存储引擎是否安装成功

在mysql命令行下执行

show engines;

如果出现如下图红色方框内的信息说明SphinxSE已经安装成功!

安装Sphinx全文检索服务器

Sphinx默认不支持中文索引及检索,以前用Coreseek的补丁来解决,目前Coreseek不单独提供补丁文件,而基于sphinx开发了Coreseek全文检索服务器,Coreseek应该是现在用的最多的sphinx中文全文检索,它提供了为Sphinx设计的中文分词包LibMMSeg包含mmseg中文分词,其实coreseek-3.2.14.tar.gz中已经包含了sphinx,前面安装SphinxSE时也可以使用这个压缩包里的mysqlse。

我们来看一下的安装过程:

安装autoconf

Bzip2 –dautoconf-2.65.tar.bz2

tar xvfautoconf-2.65.tar

cdautoconf-2.65

./configure--prefix=/usr

make

make install

cd ..

安装Coreseek

tar zxvfcoreseek-3.2.14.tar.gz

cdcoreseek-3.2.14

cdmmseg-3.2.14/

./bootstrap

./configure--prefix=/usr/local/mmseg3

make

make install

cd../csft-3.2.14/

shbuildconf.sh

./configure--prefix=/usr/local/coreseek --without-python --without-unixodbc --with-mmseg--with-mmseg-includes=/usr/local/mmseg3/include/mmseg/--with-mmseg-libs=/usr/local/mmseg3/lib/ --with-mysql=/usr/local/webserver/mysql--host=arm

make

make install

ln -s/usr/local/webserver/mysql/lib/mysql/libmysqlclient.so.16 /usr/lib

cd/usr/local/coreseek/etc

进入配置目录通过命令ls可以看到3个文件

example.sqlsphinx.conf.distsphinx-min.conf.dist

其中example.sql是示例sql脚本我们将其导入到数据库中的test数据库中作为测试数据(会创建两张表documents和tags)

vi sphinx.conf

输入以下内容

#定义一个数据库源,名字为src1

source src1

{

type=mysql

sql_host=localhost

sql_user=root

sql_pass=

sql_db= test

sql_port=3306# optional, default is 3306

sql_sock= /tmp/mysql.sock

sql_query_pre= SET NAMES utf8

sql_query=\

SELECT id,title,content FROM songs

sql_query_info= SELECT * FROM songs WHERE id=$id

}

#定义建立索引项

index test1

{

source=src1

path=/usr/local/coreseek/var/data/test1

charset_type= zh_cn.utf-8

charset_dictpath= /usr/local/mmseg3/etc/

}

#建索引程序的设置

indexer

{

#建索引时所用的内存限制

mem_limit=32M

}

#提供服务的进程配置

searchd

{

port=9312

log=/usr/local/coreseek/var/log/searchd.log

query_log=/usr/local/coreseek/var/log/query.log

read_timeout=5

max_children=30

pid_file=/usr/local/coreseek/var/log/searchd.pid

max_matches=1000

seamless_rotate= 1

preopen_indexes= 0

unlink_old=1

}

说明:

代码段source src1{***}代表数据源里面主要包含了数据库的配置信息,src1表示数据源名字,可以随便写。

代码段index test1{***}代表为哪个数据源创建索引,与source ***是成对出现的,其中的source参数的值必须是某一个数据源的名字。

其他参数可以查看手册,这里不再赘述。

生成索引

/usr/local/coreseek/bin/indexer-c /usr/local/coreseek/etc/sphinx.conf --all

其中参数--all表示生成所有索引

当然也可以是索引的名字例如:/usr/local/coreseek/bin/indexer-c /usr/local/coreseek/etc/sphinx.conf test1

执行后可以在/usr/local/coreseek/var/data目录中看到多出一些文件,是以索引名为文件名的不同的扩展名的文件

在不启动sphinx的情况下即可测试命令:

/usr/local/coreseek/bin/search -c/usr/local/coreseek/etc/sphinx.conf number

可以看到将内容中含有number数据的数据查询出来。

/usr/local/coreseek/bin/search

-c /usr/local/coreseek/etc/sphinx.conf研究生创业

可以看到我们输入的查询文字已经被拆分成了两个词,只是因为我们的测试数据中没有中文数据查询结果为空。我们插入几条新数据。

INSERT INTO`test`.`documents` (

`id` ,

`group_id` ,

`group_id2` ,

`date_added` ,

`title` ,

`content`

)

VALUES (

NULL , '2',

'3', '2011-02-01 00:37:12', '研究生的故事', '研究生自主创业'

), (

NULL , '1',

'1', '2011-01-28 00:38:22', '研究', '为了创业而研究生命科学'

);

我们再来看以下数据库中的主要数据

插入新数据后需要重新生成索引

/usr/local/coreseek/bin/indexer-c /usr/local/coreseek/etc/sphinx.conf test1

然后执行查询测试/usr/local/coreseek/bin/search -c /usr/local/coreseek/etc/sphinx.conf研究生创业

我们搜索的词语是“研究生创业”,可以看到词语被拆分成了研究生和创业两个词,虽然有两条记录都包含“创业和”研究生”这几个字但是“研究生命科学”中的“研究生”三个字虽然是紧挨着的但是不是一个词语,结果是只匹配一条“研究生自主创业”,我们在搜索“研究”这个词语

/usr/local/coreseek/bin/search

-c /usr/local/coreseek/etc/sphinx.conf研究

同样匹配一条记录,而“研究生的故事”和“研究生自主创业”的词语却没有被查询出来,可以看出sphinx与分词技术结合可以匹配出相关度更高的结果。

当然我们的目的不仅限与命令行下的测试,我们可以通过搜索API调用来执行搜索,搜索API支持PHP、Python、Perl、Rudy和Java。如果从PHP脚本检索需要先启动守护进程searchd,PHP脚本需要连接到searchd上进行检索:

/usr/local/coreseek/bin/searchd

-c /usr/local/coreseek/etc/sphinx.conf

在解压后的sphinx-0.9.9/api目录下的sphinxapi.php就是sphinx官方为我们提供的API文件(其实也可以使用PHP的sphinx扩展),只需将其包含进自己的PHP脚本文件就可以了。

示例代码:


include('sphinxapi.php');

$cl=newSphinxClient();

//设置sphinx服务器地址与端口,如果是本机则可以为localhost

$cl->SetServer("192.168.16.6",9312);

//以下设置用于返回数组形式的结果

$cl->SetArrayResult (true);

//$cl->SetMatchMode( SPH_MATCH_ANY);//匹配模式

//$cl->SetFilter( 'group_id', array( 2 ) );

$result=$cl->Query('研究生创业','test1');//参数 关键字索引名

if($result===false) {

echo"Query failed: ".$cl->GetLastError() .".\n";

}

else{

if($cl->GetLastWarning() ) {

echo"WARNING: ".$cl->GetLastWarning() ."";

}

echo'<pre>';

print_r($result);

}

?>

执行后的结果:

Array

(

[error] =>

[warning] =>

[status] => 0

[fields] => Array

(

[0] => title

[1] => content

)

[attrs] => Array

(

[group_id] => 1

[date_added] => 2

)

[matches] => Array

(

[5] => Array

(

[weight] => 2

[attrs] => Array

(

[group_id] => 2

[date_added] => 1296491832

)

)

)

[total] => 1

[total_found] => 1

[time] => 0.078

[words] => Array

(

[研究生] =>Array

(

[docs] => 1

[hits] => 2

)

[创业] =>Array

(

[docs] => 2

[hits] => 2

)

)

)

在matches中的就是查询结果,我们注意到sphinx是将记录中的主键ID值返回而不是返回所有数据,上面的例子中的键名5就是记录的ID(如果在查询前执行$cl->SetArrayResult

( true );则数组结构会有些许差异)。至此搜索服务器已经为我们完成了大部分工作,接下来我们通过主键ID值来查询我们想要的数据就可以了。

Sphinx存储引擎的使用

SphinxSE是一个可以编译进MySQL 5.x版本的MySQL存储引擎,它利用了该版本MySQL的插件式体系结构。尽管被称作“存储引擎”,SphinxSE自身其实并不存储任何数据。它其实是一个允许MySQL服务器与searchd交互并获取搜索结果的嵌入式客户端。所有的索引和搜索都发生在MySQL之外。

SphinxSE的适用于:

 使将MySQL FTS应用程序移植到Sphinx

 使没有Sphinx API的那些语言也可以使用Sphinx

 当需要在MySQL端对Sphinx结果集做额外处理(例如对原始文档表做JOIN,MySQL端的额外过滤等等)时提供优化。

要通过SphinxSE搜索,需要建立特殊的ENGINE=SPHINX的“搜索表”,然后使用SELECT语句从中检索,把全文查询放在WHERE子句中。

创建一张表t1

CREATE TABLEt1

(

idINTEGER UNSIGNED NOT NULL,

weightINTEGER NOT NULL,

queryVARCHAR(3072) NOT NULL,

group_idINTEGER,

INDEX(query)

)ENGINE=SPHINX CONNECTION="sphinx://localhost:9312/test1";

搜索表前三列的类型必须是INTEGER,INTEGER和VARCHAR,这三列分别对应文档ID,匹配权值和搜索查询。查询列必须被索引,其他列必须无索引。列的名字会被忽略,所以可以任意命名,参数CONNECTION来指定用这个表搜索时的默认搜索主机、端口号和索引,语法格式:CONNECTION="sphinx://HOST:PORT/INDEXNAME"。

执行SQL语句select d.id,d.title,d.content from t1 join documents as d on t1.id

= d.id and t1.query = '研究生创业';

+----+--------------------+-----------------------+

| id |title| content|

+----+--------------------+-----------------------+

|5 |研究生的故事|研究生自主创业|

+----+--------------------+-----------------------+

1 row in set(0.04 sec)

结果返回了我们想要的数据,可见利用SphinxSE可以仅仅在SQL语句上做很小的改动即可很方便的实现全文检索!

主索引+增量索引

前提:数据不会被改变

第一步:建表:(用来存索引过的最大的记录id)

Create table a

{

Id int unsigned not nullprimary key,

Max_idint unsigned,

}

第二步:修改配置文件为:见sphinx配置文件.doc

第三步:先执行./bin/indexer–c ./etc/sphinx.conf –test1生成所有的索引-〉一个数据源的主查询,只有第一次执行

第四步:定期执行:./bin/indexer–c./etc/sphinx.conf delta --rotateà生成增量的索引文件

第五步:合并到主索引中./bin/indexer –merge test1 delta –c ./etc/sphinx.conf --rotate

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容