您的位置:首页 > 运维架构 > Linux

在Linux下安装Sphinx+MySQL5.1x+SphinxSE+mmseg中文分词

2013-06-08 21:28 477 查看
一、原生MySQL存储引擎检索流程:



二、基于Sphinx存储引擎检索:



三、安装前准备文件:



四、开始安装:

1)通过yum命令更新依赖包(与php环境搭建依赖包一起更新了)

yum -y install gcc g++ gcc-c++ libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel libxml2 libxml2-devel zlib zlib-devel glibc glibc-devel glib2 glib2-devel bzip2 bzip2-devel ncurses ncurses-devel curl curl-devel e2fsprogs e2fsprogs-devel krb5 krb5-devel libidn libidn-devel openssl openssl-devel openldap openldap-devel nss_ldap openldap-clients openldap-servers patch libtool automake imake mysql-devel expat-devel

2)安装MySQL+SphinxSE,(进入软件包所在的目录)

tar zxvf mysql-5.1.55.tar.gz
tar zxvf sphinx-0.9.9.tar.gz
cp -r sphinx-0.9.9/mysqlse/ mysql-5.1.55/storage/sphinx
cd mysql-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 -R mysql:mysql /usr/local/webserver/mysql
cd ../

创建目录
mkdir -p /data0/mysql/3306/data/
mkdir -p /data0/mysql/3306/binlog/
mkdir -p /data0/mysql/3306/relaylog/
chown -R mysql:mysql /data0/mysql/

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

/usr/local/webserver/mysql/bin/mysql_install_db --basedir=/usr/local/webserver/mysql --datadir=/data0/mysql/3306/data --user=mysql
vi /data0/mysql/3306/my.cnf

输入 
[client]
character-set-server = utf8
port    = 3306
socket  = /tmp/mysql.sock

[mysqld]
character-set-server = utf8
replicate-ignore-db = mysql
replicate-ignore-db = test
replicate-ignore-db = information_schema
user    = mysql
port    = 3306
socket  = /tmp/mysql.sock
basedir = /usr/local/webserver/mysql
datadir = /data0/mysql/3306/data
log-error = /data0/mysql/3306/mysql_error.log
pid-file = /data0/mysql/3306/mysql.pid
open_files_limit    = 10240
back_log = 600
max_connections = 5000
max_connect_errors = 6000
table_cache = 614
external-locking = FALSE
max_allowed_packet = 4M
sort_buffer_size = 1M
join_buffer_size = 1M
thread_cache_size = 300
#thread_concurrency = 8
query_cache_size = 4M
query_cache_limit = 1M
query_cache_min_res_unit = 2k
default-storage-engine = MyISAM
thread_stack = 192K
transaction_isolation = READ-COMMITTED
tmp_table_size = 4M
max_heap_table_size = 16M
long_query_time = 3
log-slave-updates
log-bin = /data0/mysql/3306/binlog/binlog
binlog_cache_size = 1M
binlog_format = MIXED
max_binlog_cache_size = 2M
max_binlog_size = 1G
relay-log-index = /data0/mysql/3306/relaylog/relaylog
relay-log-info-file = /data0/mysql/3306/relaylog/relaylog
relay-log = /data0/mysql/3306/relaylog/relaylog
expire_logs_days = 30
key_buffer_size = 8M
read_buffer_size = 1M
read_rnd_buffer_size = 2M
bulk_insert_buffer_size = 4M
myisam_sort_buffer_size = 16M
myisam_max_sort_file_size = 1G
myisam_repair_threads = 1
myisam_recover

interactive_timeout = 120
wait_timeout = 120

skip-name-resolve
#master-connect-retry = 10
slave-skip-errors = 1032,1062,126,1114,1146,1048,1396

#master-host     =   192.168.1.2
#master-user     =   username
#master-password =   password
#master-port     =  3306

server-id = 1

innodb_additional_mem_pool_size = 8M
innodb_buffer_pool_size = 64M
innodb_data_file_path = ibdata1:256M:autoextend
innodb_file_io_threads = 4
innodb_thread_concurrency = 8
innodb_flush_log_at_trx_commit = 2
innodb_log_buffer_size = 4M
innodb_log_file_size = 32M
innodb_log_files_in_group = 3
innodb_max_dirty_pages_pct = 90
innodb_lock_wait_timeout = 120
innodb_file_per_table = 0

#log-slow-queries = /data0/mysql/3306/slow.log
#long_query_time = 10

[mysqldump]
quick
max_allowed_packet = 8M

===========================================================================
创建shell管理脚本
vi /data0/mysql/3306/mysql
输入
#!/bin/sh

mysql_port=3306
mysql_username="root"
mysql_password="12345678"

function_start_mysql()
{
    printf "Starting MySQL...\n"
    /bin/sh /usr/local/webserver/mysql/bin/mysqld_safe --defaults-file=/data0/mysql/${mysql_port}/my.cnf 2>&1 > /dev/null &
}

function_stop_mysql()
{
    printf "Stoping MySQL...\n"
    /usr/local/webserver/mysql/bin/mysqladmin -u ${mysql_username} -p${mysql_password} -S /tmp/mysql.sock shutdown
}

function_restart_mysql()
{
    printf "Restarting MySQL...\n"
    function_stop_mysql
    sleep 5
    function_start_mysql
}

function_kill_mysql()
{
    kill -9 $(ps -ef | grep 'bin/mysqld_safe' | grep ${mysql_port} | awk '{printf $2}')
    kill -9 $(ps -ef | grep 'libexec/mysqld' | grep ${mysql_port} | awk '{printf $2}')
}

if [ "$1" = "start" ]; then
    function_start_mysql
elif [ "$1" = "stop" ]; then
    function_stop_mysql
elif [ "$1" = "restart" ]; then
function_restart_mysql
elif [ "$1" = "kill" ]; then
function_kill_mysql
else
    printf "Usage: /data0/mysql/${mysql_port}/mysql {start|stop|restart|kill}\n"
fi

======================================================================================
chmod +x /data0/mysql/3306/mysql
启动mysql
/data0/mysql/3306/mysql start
登陆mysql
/usr/local/webserver/mysql/bin/mysql -u root -p -S /tmp/mysql.sock
创建用户并赋予权限
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY '12345678';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'127.0.0.1' IDENTIFIED BY '12345678';
======================================================================================

安装完成启动MySQL后查看sphinx存储引擎是否安装成功
在mysql命令行下执行

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



3)安装Sphinx全文检索服务器

说明:

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

安装autoconf
tar zxvf autoconf-2.64.tar.gz
cd autoconf-2.64
./configure --prefix=/usr
make
make install
cd ..
安装Coreseek
tar zxvf coreseek-3.2.14.tar.gz
cd coreseek-3.2.14
cd mmseg-3.2.14/
./bootstrap
./configure --prefix=/usr/local/mmseg3
make
make install
cd ../csft-3.2.14/
sh buildconf.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 --host=arm
make
make install
注:若上面执行完make后报如下错误:



[align=left]则进入当前目录下的src目录,编辑Makefile文件 将[/align]
[align=left]LIBS = -lm -lz -lexpat -L/usr/local/lib -lrt  -lpthread[/align]
[align=left]修改为LIBS = -lm -lz -lexpat -liconv -L/usr/local/lib -lrt  -lpthread[/align]
[align=left]然后重新编即可。[/align]
[align=left]
[/align]
[align=left]
[/align]
cd /usr/local/coreseek/etc
进入配置目录通过命令ls可以看到3个文件
example.sql  sphinx.conf.dist  sphinx-min.conf.dist
其中example.sql是示例sql脚本我们将其导入到数据库中的test数据库中作为测试数据(会创建两张表 documents和tags)
vi sphinx.conf
输入以下内容
source src1
{
type = mysql
sql_host = localhost
sql_user = root
sql_pass =12345678
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, group_id, UNIX_TIMESTAMP(date_added) AS date_added, title, content \
FROM documents
sql_attr_uint = group_id
sql_attr_timestamp = date_added
sql_query_info = SELECT * FROM documents WHERE id=$id
}
index test1
{
source = src1
path = /usr/local/coreseek/var/data/test1
docinfo = extern
charset_type = zh_cn.utf-8
mlock = 0
morphology = none
min_word_len = 1
html_strip = 0
charset_dictpath = /usr/local/mmseg3/etc/
ngram_len                    = 0
}
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.conftest1
执行后可以在/usr/local/coreseek/var/data目录中看到多出一些文件,是以索引名为文件名的不同的扩展名的文件
在不启动sphinx的情况下即可测试命令:

[align=left]
[/align]
[align=left]五、测试[/align]
[align=left]
[/align]
[align=left]1)测试MySQL+sphinx[/align]
/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 number --filter group_id 2
限定group_id 为2 返回一条记录

同样也可以测试中文(需将命令行终端编码调整为utf-8),如下:

/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脚本文件就可以了。

示例代码:
<?php
include('sphinxapi.php');

$cl = new SphinxClient();
//设置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
ab4b
] => 2
                    [hits] => 2
                )

        )

)

在matches中的就是查询结果,我们注意到sphinx是将记录中的主键ID值返回而不是返回所有数据,上面的例子中的键名5就是记录的ID(如果在查询前执行$cl->SetArrayResult (
true );则数组结构会有些许差异)。至此搜索服务器已经为我们完成了大部分工作,接下来我们通过主键ID值来查询我们想要的数据就可以了。

2) 测试MySQL+Sphinx EX

说明:

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

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

首先创建一张表t1

CREATE TABLE t1
(
id          INTEGER UNSIGNED NOT NULL,
weight      INTEGER NOT NULL,
query       VARCHAR(3072) NOT NULL,
group_id    INTEGER,
INDEX(query)
) ENGINE=SPHINX CONNECTION="sphinx://localhost:9312/test1";

搜索表前三列的类型必须是INTEGER,INTEGER和VARCHAR,这三列分别对应文档ID,匹配权值和搜索查询。查询列必须被索引,其他列必须无索引。列的名字会被忽略,所以可以任意命名,参数CONNECTION来指定用这个表搜索时的默认搜索主机、端口号和索引,语法格式:CONNECTION="sphinx://HOST:ORT/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语句上做很小的改动即可很方便的实现全文检索!

在php程序中测试也一样,如下代码:

<?php
mysql_connect('192.168.1.75', 'user', '12345678');
mysql_select_db('test');
mysql_query('set names uft8');

if($_POST["searchwords"]){
$search = $_POST["searchwords"];
$result = mysql_query("select a.id,a.title,a.content,a.author from t2 join article as a on t2.id = a.id and t2.query = '$search'");
while($rows = mysql_fetch_assoc($result)){
$arr[] = $rows;
}
echo "<table border=1>";
echo "<th>id</th><th>title</th><th>content</th>";
foreach($arr as $val){
echo '<tr>'.'<td>'.$val['id'].'</td>'.'<td>'.$val['title'].'</td>'.'<td>'.$val['content'].'</td>'.'</tr>';
}
echo "</table>";
}
?>


安装与简单测试到此为止!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  MySQL Sphinx