Sphinx&coreseek实现中文分词索引

Sphinx&coreseek实现中文分词索引

Write By CS逍遥剑仙

我的主页: www.csxiaoyao.com

GitHub: github.com/csxiaoyaojianxian

Email: sunjianfeng@csxiaoyao.com

QQ: 1724338257

1. 简介

众所周知,mysql等数据库的LIKE模糊搜索不支持索引,因此查询效率极低,需要结合第三方索引引擎程序(索引程序)来提高查询性能。开源索引程序有3大类:lucene系(java开发,包括solr和elasticsearch)、sphinx(c++开发,简单高性能)、Xapian(c++开发),其中lucene由于hadoop的原因名气最大,sphinx因为简单可靠,代码结构优良,性能非常好,在国内大型网站中使用最广。sphinx是国外的一款搜索软件,但是本身不支持中文索引,coreseek在sphinx基础上增加了中文分词功能,支持了中文索引。本文主要介绍Sphinx和coreseek的使用。

2. Sphinx使用流程

step1: Sphinx对数据库数据创建索引,使用分词技术分别对单词存储记录id(当数据量大时较费时间)

step2: 启动Sphinx服务器

step3: 查询程序首先将关键词发送给Sphinx服务器查询,sphinx返回查询结果在原数据库表中的id(主键)

step4: 查询程序根据返回的主键id在原数据库中取出相应记录

3. 最佳实践

GitHub: https://github.com/sphinxsearch/sphinx

### ./configure –prefix=/usr/local/sphinx #注意:这里sphinx已经默认支持了mysql
### ./configure --prefix=/usr/local/sphinx --with-mysql=/usr/local/mysql
$ ./configure --prefix=/usr/local/sphinx --with-mysql=/Applications/MAMP/Library
$ make && make install
# 修改配置文件
$ cd /usr/local/sphinx/etc
$ cp sphinx.conf.dist sphinx.conf
$ vim sphinx.conf # 修改配置
# 导入etc下的测试数据
$ mysql -uroot -p test < example.sql
# 建立索引文件
$ bin/indexer -c etc/sphinx.conf
# 运行sphinx
$ bin/searchd
# 运行php测试
$ php api/test.php -h localhost

4. coreseek安装

coreseek在Sphinx基础上支持了中文扩展,下载coreseek安装包解压后得到两个目录csft和mmseg,csft-xxx相当于sphinx安装目录,mmseg-xxx为中文分词安装包

# 安装中文分词库 cd mmseg-xxx,可能需要额外按照automake
$ ./configure --prefix=/usr/local/mmseg/
# 安装coreseek cd csft-xxx
$ ./configure --prefix=/usr/local/coreseek --with-mysql=/usr/local/mysql --with-mmseg-includes=/usr/local/mmseg/include/mmseg/ --with-mmseg-libs=/usr/local/mmseg/lib/
$ make && make install

5. 相关配置

5.1 配置文件格式

sphinx.conf的内容组成格式为:

source <源名称1>{
	…
}
index <索引名称1>{
	source = <源名称1>
	…
}
source <源名称2>{
	…
}
index <索引名称2>{
	source = <源名称2>
	…
}
indexer{
	…
}
searchd{
	…
}

5.2 建立数据源(需建立索引的数据)

# 配置格式参考,默认情况下修改数据库用户名和密码即可
source user_source_1
{
    type                    = mysql             // 数据库类型
    sql_host                = localhost         // 所连接的 ip
    sql_user                = root              // 数据库用户名
    sql_pass                = root              // 数据库密码
    sql_db                  = test              // 数据库名称
    sql_port                = 3306              // 数据库端口
    sql_query_pre           = SET NAMES utf8    // 数据库预查询
    # 主查询,执行结果作为数据源
    # 注意:
    # 1. 取出的数据中,必须有id(若无名称为id的字段,可以使用别名),id为主键
    # 2. id后面的字段创建索引
    sql_query               = SELECT id,name,age FROM user
	...
}

5.3 创建索引

index user_index_1
{
	# 对应创建的数据源
    source					= user_source_1
    # 指定索引文件存放路径
    path					= xxxxx/var/data/xxx
    ...
    # 中文分词配置
    charset_dispath			= xxxxx/etc/
    charset_type			= zh_cn.utf-8
}

5.4 配置服务器

searchd
{
	...
	# 指定进程文件、日志文件、查询日志文件的位置
	pid_file				= xxx
	log						= xxx
	query_log				= xxx
}

6. 创建索引并启动服务器

使用 bin 下的 indexer 创建索引

$ indexer -c <配置文件> --all | <索引文件名>

使用searchd启动sphinx服务器

7. PHP应用: 关键词查询并高亮显示

<?php
    header("content-type:text/html;charset=utf8");
    require 'sphinxapi.php';
    // 创建对象
    $sc = new SphinxClient();
    // 连接服务器
    $sc->setServer('localhost','9312');
    // 执行查询 query('查询关键词','使用索引')
    $keywords = 'CS逍遥剑仙';
    $indexName = 'user_index_1';
    $res = $sc->query($keywords,$indexName);
    // 设置查询数量,(offset limit)
    $sc->setLimits(20, 5);
    // 返回结果
    $ids = $res['matches'];
    $id = implode(',', array_keys($ids));
    // 连接mysql服务器
    $conn = mysql_connect('localhost','root','root');
    mysql_query('use php');
    mysql_query('set names utf8');
    mysql_query("select id,name,from user where id in($id)");
    $data = array();
    while($row = mysql_fetch_assoc($result)){
        $data[] = $row;
    }
    // 输出数据
    foreach($data as $v){
    	// param1: 输出的数据
    	// param2: 索引名称
    	// param3: 关键词
    	// param4: 设置关键词显示的样式
    	// return: 索引数组
        $v = $sc->buildExcerpts($v,$indexName,$keywords,array(
        	'before_match'=>'<font style="color:#f00">',
        	'after_match'=>'</font>'
        ));
        echo $v[1].'<br/>'.$v[2].'<hr>';
    }
    print_r($data);
?>

8. Sphinx匹配模式

提供了5种模式:

SPH_MATCH_ALL: (默认)匹配所有查询词,会对查询关键词分词,查询结果必须同时包含所有关键词

SPH_MATCH_ANY: 查询关键词分词,查询结果匹配其中任意一个即可

SPH_MATCH_PHRASE: 查询关键词不分词,查询结果必须严格匹配整个查询关键词

SPH_MATCH_EXTENDED: 支持扩展语法,支持@字段查询,如查询title包含abc,content包含bcd:'@title abc @content bcd'

SPH_MATCH_BOOLEAN: 与/或/非/分组,& / or / ! / ()

<?php
    ...
    $keywords = 'CS逍遥剑仙';
    $indexName = 'user_index_1';
    // 设置匹配模式
    $sc->setMatchMode(SPH_MATCH_ALL);
    $res = $sc->query($keywords,$indexName);
    ...

9. 增量索引

主表数据增加需要增加索引,如果数据量大,直接重建索引会很慢,可通过对增加的数据单独建立索引,再把建立的索引合并到主索引。

9.1 确定新增数据的方案

(1) 创建一张表,记录数据的最大id

mysql> create table t(id int)engine myisam charset utf8;
mysql> insert into t values(10000)

# 增量索引配置
source src_zl 
{
    ...
    sql_query			= select id,name from user where id>(select id from t)
    # 创建增量索引时更新表中最大id
    sql_query_post		= update a set id = (select max(id) from user)
}
index index_zl 
{
    source				= src_zl
    path				= /usr/local/sphinx/var/data/src_zl
    ...
}

(2) 创建增量索引,rotate强制执行

$ bin/indexer -c /usr/local/sphinx/etc/sphinx.conf index_zl --rotate

(3) 增量索引合入主索引

$ bin/indexer -c /usr/local/sphinx/etc/sphinx.conf --merge user_index_1 index_zl --rotate

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏博客园迁移

几种事务的隔离级别,InnoDB如何实现?

隔离性是指,多个用户的并发事务访问同一个数据库时,一个用户的事务不应该被其他用户的事务干扰,多个并发事务之间要相互隔离。

771
来自专栏jouypub

Hive日常操作

根据分区查询数据:select table_coulm from table_name where partition_name = '2018-11-01';

2083
来自专栏idba

漫谈死锁

一 前言 死锁是每个MySQL DBA 都会遇到的技术问题,本文是自己针对死锁学习的一个总结,了解死锁是什么,MySQL如何检测死锁,处理死锁,死锁的案例,...

1354
来自专栏应用案例

索引,视图,存储过程和触发器文档

实验案例一:验证索引的作用 1、首先创建一个数据量大的表,名称为“学生表”,分别有三列,学号,姓名和班级,如下图所示,学号为自动编号,班级为默认值“一班”。 ?...

2268
来自专栏james大数据架构

微软官方提供的用于监控MS SQL Server运行状况的工具及SQL语句

Microsoft SQL Server 2005 提供了一些工具来监控数据库。方法之一是动态管理视图。动态管理视图 (DMV) 和动态管理函数 (DMF) 返...

2597
来自专栏乐沙弥的世界

Oracle 10.2.0.1 升级到 10.2.0.4

数据库升级并不难,只要遵循其步骤,一般问题不大。但是升级失败的情况也是屡见不鲜,尤其是生产数据库的升级,搞不定的时候甚至要创建SR。

1393
来自专栏源哥的专栏

如何对表操作进行监控

我们在跟踪定位一些系统问题的时候,经常需要知道哪些地方对一个表进行了操作,查询代码很麻烦,其实有一个简单的方法,就是跟踪表, 如下语句,就可以给表t_table...

1192
来自专栏Python

MySQL常见的库操作,表操作,数据操作集锦及一些注意事项

一 库操作(文件夹) 1 数据库命名规则 可以由字母、数字、下划线、@、#、$ 区分大小写 唯一性 不能使用关键字如 create select 不能单独使用数...

2469
来自专栏自由而无用的灵魂的碎碎念

Oracle:创建db_link

global_name也就是数据库的全局数据库名,可已使用select * from global_name;查询:

862
来自专栏野路子程序员

整合用户篇—Oauth2理解与构造简单的系统

3758

扫码关注云+社区

领取腾讯云代金券