Sphinx初涉猎

1,152 阅读5分钟

之前来杭州面试的时候被问到过这样一个问题,如果让你去实现一个关键词的全文检索,你会如何去实现。我第一反应是说使用全文索引,因为like+%这种模糊查询的方式是比较慢的,这点我是知道的。然后面试官又问:你了解这个全文索引的性能吗,假如数据量特别大时又该如何处理。这下把我问懵了,本身全文索引在工作中几乎没怎么用到过,自己对这方面的知识又了解的比较少...看了我的反应,面试官也就没问下去...

最近,上上周在浏览某论坛时发现了一个能解决大量数据做一个关键词搜索功能的好东西——sphinx(司芬克斯)。这篇博客主要介绍sphinx的一些基本知识和如何安装,还有这几天学习下来新手碰到的一些问题和注意点。

本来想上周更新这篇博客的,但上周公司组织团建,最近公司又有项目赶着上线,所以拖到了这周。之前说到每天保持1小时到2小时的学习时间,庆幸的是这flag还未倒。最近准备在学习laravel框架,因为之前一直在用Thinkphp,从3版本到5版本都使用过,前段时间面试期间发现不少公司有用到laravel,因此想先学习了解一下,比较一下与Thinkphp有何不同。对于sphinx的学习纯属个人兴趣,因为看了一下这东西,涉及的知识点还是蛮多的,所以打算把这个东西的学习放到周末,博客也会跟着更新。

下面做一个简单的介绍:

Sphinx是一个基于SQL的全文检索引擎,可以结合MySQL,PostgreSQL做全文搜索。Sphinx特别为一些脚本语言设计搜索API接口,如PHP,Python,Perl,Ruby等,同时为MySQL也设计了一个存储引擎插件。Sphinx 单一索引最大可包含1亿条记录,在1千万条记录情况下的查询速度为0.x秒(毫秒级)。Sphinx创建索引的速度为:创建100万条记录的索引只需 3~4分钟,创建1000万条记录的索引可以在50分钟内完成,而只包含最新10万条记录的增量索引,重建一次只需几十秒。

之前一直尝试在mac上装sphinx,但是苦于网上教程太少,安装中出现各种各样未知的bug,无奈只能放弃,选择了虚拟机。

下面介绍sphinx的安装步骤

1.下载sphinx包

方法有两种:
1.官网直接下来安装包,然后利用ftp传到服务器上,
2.wget命令下载 wget http://sphinxsearch.com/files/sphinx-2.3.1-beta.tar.gz)
这里说明一下sphinx的版本,官方的最新版本是3.1.1版,而我装的是2.3.1版,也就是上面这版,然后sphinx中文网上
给的教程是0.9.9版,具体版本之间的差异我也不是清楚,没有深入去了解,但是最大的一个区别是,0.9.9版里面是自带的search的,而我装的2.3.1版里面就没有这个东西了,这个东西是它自带的一个搜索工具,没有这个的话只能通过Api去测试。

2.解压,安装,编译

一般都下载到/usr/local/src目录下
安装一般都安装到/usr/local/sphinx    (sphinx这个目录是自定义的)
在此目录使用tar命令解压 :tar zxvf sphinx-2.3.1-beta.tar.gz
安装命令:./configure   --prefix=/usr/local/sphinx  (--prefix=安装目录)
make   生成编译文件
make install 进行编译 
(如果这里出现编译错误或者其他未知错误,自行通过geogle解决,我安装下来全部一路绿灯)。

3.配置

1.我们在mysql中建立一个test数据库,数据库中有数据表post
CREATE TABLE `post` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(254)DEFAULT NULL,
`content` text,PRIMARY KEY (`id`) 
)ENGINE=InnoDB 
AUTO_INCREMENT=8 
DEFAULT CHARSET=utf8;
我们插入几条数据

INSERT INTO `post` (title,content) VALUES ('php', 'php111');
INSERT INTO `post` (title,content) VALUES ('linux', 'linux222');
INSERT INTO `post` (title,content) VALUES ('apche', 'apche222');

这里说下,shpinx对中文是不支持的,只对英文有效,如果要进行中文分词查询,比如装coreseek或者sfc。
关于这两个东西我接下来会去学习,争取能够慢慢更新上来
我看到有篇博客上写着,通过配置charset_table和ngram_chars就可以进行中文分词,但其实是不合理的。
中文文档上有说

2.配置conf文件
cd /usr/local/sphinx/etc
里面有个sphinx.conf.dist,这是个模版文件,可以使用cp sphinx.conf.dist sphinx.conf
然后在sphinx.conf上修改配置,或者直接新建sphinx.conf文件。

//数据源配置,也就是数据来源
source main
{
        type                    = mysql
        sql_host                = HOST //数据库
        sql_user                = USER //用户名
        sql_pass                = PASS //数据库密码
        sql_db                  = post 数据库名称
        sql_port                = 3306  # optional, default is 3306
        sql_query_pre           = SET NAMES utf8 
        sql_query               = select id,title,content from post
}
    //索引配置
index main
{
        source                  = item //数据源
        path                    = /usr/local/src/sphinx/var/main 索引存放目录
        min_word_len            = 1 
        ngram_len               = 1
        ngram_chars             = U+3000..U+2FA1F
}


indexer
{
        mem_limit               = 128M
}

//搜索服务
searchd
{
        listen                  = 9312
        listen                  = 9306:mysql41
        log                     = /usr/local/src/sphinx/var/log/searchd.log
        query_log               = /usr/local/src/sphinx/var/log/query.log
        read_timeout            = 5
        max_children            = 30
        pid_file                = /usr/local/src/sphinx/var/log/searchd.pid
        seamless_rotate         = 1
        preopen_indexes         = 1
        unlink_old              = 1
        binlog_path             = /usr/local/src/sphinx/var/main
}

主要的配置就是这些,数据源配置,索引配置,当然配置还有很多,我这些只是一个最基本的。
可以参考https://blog.csdn.net/phachon/article/details/52450970

接下来就是生成索引和启动serached服务

# 生成索引
/usr/local/sphinx/bin/indexer --all
# 打开 sphinx 进程
/usr/local/sphinx/bin/searchd

** 4.测试和使用** 接下来就是测试了,因为我装的版本里面没有search,所以只能用api测试 在我们刚才下载来的sphinx包里面有个api文件夹,里面有各种语言的api cd /usr/local/src/sphinx-2.3.1-beta/api

我们需要的就是这个sphinxapi.php,把这个api复制出来,
php调用
header("Content-type:text/html;charset=utf-8");
require_once 'sphinxapi.php'; 
$sc = new SphinxClient();
$sc->SetServer('127.0.0.1',3312);
$sc->SetMatchMode(SPH_MATCH_ALL);
$sc->SetArrayResult(TRUE);
$res = $sc->Query('php');
var_dump($res);
接下来正常情况就可以查询出来了。

今天有点晚了,明天还要摸鱼一些细节的地方没有描述好,改天再把文章更新的完整点。 接下来我应该会持续更新sphinx,也希望有大佬看到能够交流指点。