mysql 分表 sphinx_centos 6 多库分表之后,使用coreseek/sphinx中文分词搜索

本文介绍了一个新项目中采用Sphinx和Coreseek进行分表搜索优化的过程,包括解决主键为bigint和字符串的问题、实现模糊搜索、多表联合查询索引建立、多库数据库配置管理和多个索引配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

近段时间的一个新项目,使用了分表之后,mysql 做一些搜索就只能使用联表做视图,对搜索很不友好,我们选择了,sphinx/coreseek,因为基本能满足我们的需求,当然还是其他的Xunsearch,Lucene,都是不错。这整个过程中,我们遇到了不少的问题,,希望以下内容能帮助到你。

环境版本

os:centos 6.6 64位,ceonts 7在编译coreseek时会报各种automake等错误

php5.4 + mysql5.6

安装过程略过

网上有很多安装之类的文章。

如果你想做搜索的表主键是bigint类型,请在编辑时加上--enable-id64

./configure --prefix=/usr/local/coreseek --without-unixodbc --with-mmseg --with-mmseg-includes=/usr/local/mmseg3/include/mmseg/ --with-mmseg-libs=/usr/local/mmseg3/lib/ --with-mysql --enable-id64

使用过程中碰到的问题

1、主键Id为bigint,长度为20位

我们将用户表分了50个单表,如user_0,user_1,...user_49,里面的用户ID,都是使用mysql的uuid_short()函数生成,如果使用多库的情况下请使用同一台服务器生成uuid,不然长度不会统一。如果在编译过程中没有加--enable-id64,那对不起,你搜索的结果不对,但你又看不出什么错误,需要重新编译安装

2、主键是字符串,怎么破

这是官方说的:文档ID必须是第一列,而且必须是唯一的正整数值(不能是0也不能是负数),既可以是32位的也可以是64位的。所以说没有办法,只能添加一列,然后使用uuid_short(),更新并添加索引。

3、怎么做模糊搜索

在中文分词时,如中国人,在搜索中,没有结果,这怎么能忍,发现搜索拆分的词为中国,人,国人,没有将词单个拆分,其实官方说明文档里有。

MMSEG分词配置选项 mmseg分词相关的配置选项,需要保存到文件mmseg.ini,并将该配置文件放置到charset_dictpath所设置的目录中。

基本配置:

[mmseg]

seperate_number_ascii=1;;就是将字母和数字打散;

这个地方请注意,开启之后生成索引的文件会比之前大很多

4、分表或多表联合查询时应该怎么建立索引

之前我们join或复杂的sql时,发现维护起来很麻烦,可以先在数据库中新建视图,以方便做搜索。

5、如何更方便的配置管理多库数据库

source server

{

type = mysql

sql_host = 127.0.0.1

sql_user = db_user

sql_pass = db_password

sql_port = 3306

sql_query_pre = SET NAMES utf8

}

#test_user为库名

#view_user为视图表名,继承server

source test_user_view_user : server

{

sql_db = test_user

sql_query = select uid,nick,source,ctime from test_view_user

sql_field_string = nick #可全文搜索,可返回原始文本信息

sql_attr_string = source

sql_attr_string = ctime

sql_query_info = select * from test_view_user where uid = $uid

}

#test_content为库名

#view_content为视图表名,继承server

source test_content_view_content : server

{

sql_db = test_content

sql_query = select content_id,ctime,content from taoo_view_content

sql_field_string = content

sql_attr_string = ctime

sql_query_info = select * from taoo_view_content where content_id = $content_id

}

这样配置数据,可以在server源中做更多的基础配置,如用户密码统一管理,还可以做增量数据索引更新

6、配置多个索引

index test_index_user_view_user

{

source = test_user_view_user

docinfo = extern

mlock = 0

morphology = none

min_word_len = 1

ngram_len = 1

min_infix_len = 0

#这里有重要

charset_type = zh_cn.utf-8

#这里有重要

charset_dictpath = /usr/local/mmseg3/etc/

html_strip = 0

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

}

#这是继承前面的索引,没有找到更简洁的写法

index test_index_content_view_note_info : test_index_user_view_user

{

source = test_content_view_content

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

}

7、基础数据源,官网贴的

indexer

{

#最大可能的限制是2047M,官方说的

mem_limit = 1048M

}

searchd

{

listen = 9312

listen = 9306:mysql41

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

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

read_timeout = 5

client_timeout = 300

max_children = 30

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

max_matches = 1000

seamless_rotate = 1

preopen_indexes = 1

unlink_old = 1

mva_updates_pool = 1M

max_packet_size = 8M

max_filters = 256

max_filter_values = 4096

max_batch_queries = 32

workers = threads # for RT to work

}

php 简单操作类

/**

* Sphinx.php

*

* @author mingzhi.l

* @version 1.0

* @copyright 2015-2015

*/

namespace Search;

/**

* SPH_MATCH_ALL 匹配所有查询词(默认模式).

* SPH_MATCH_ANY 匹配查询词中的任意一个.

* SPH_MATCH_PHRASE 将整个查询看作一个词组,要求按顺序完整匹配.

* SPH_MATCH_BOOLEAN 将查询看作一个布尔表达式.

* SPH_MATCH_EXTENDED 将查询看作一个Sphinx内部查询语言的表达式.

* SPH_MATCH_FULLSCAN 使用完全扫描,忽略查询词汇.

* SPH_MATCH_EXTENDED2 类似 SPH_MATCH_EXTENDED ,并支持评分和权重.

*/

class Sphinx

{

static public $instance;

static public $server = 'default';

//默认服务器

static private $host = '127.0.0.1';

//默认端口

static private $port = 9312;

//超时15秒

protected $timeout = 15;

protected $_data = [];

protected $_keywords = '';

protected $_indexName = '';

private $_page = [

'page' => 1,

'page_count' => 1,

'item_count' => 0,

'item_per_page' => 20,

'item_list' => [],

];

/**

* @var \SphinxClient

*/

private $conn;

/**

* @return Sphinx

*/

static public function Instance()

{

$class = get_called_class();

if (empty(self::$instance)) {

self::$instance = new $class();

//$config = Config::get_search_sphinx(self::$server);

//self::$host = $config['host'];

//self::$port = $config['port'];

}

return self::$instance;

}

/**

* 建立链接

*

* @return Sphinx

*/

public function init()

{

$this->conn = new \SphinxClient();

$this->conn->setServer(self::$host, self::$port);

$this->conn->setMatchMode(SPH_MATCH_ANY);//匹配查询词中的任意一个.

$this->conn->setMaxQueryTime($this->timeout);

$this->conn->SetArrayResult(true);//控制搜索结果集的返回格式

return $this;

}

/**

* 执行搜索查询

*

* @param $keyword

* @param $indexName

* @return $this

* @throws Exception

*/

public function query($keyword, $indexName)

{

if (empty($keyword) || empty($indexName)) {

throw new Exception('query error: keyword or indexName is null');

}

$this->_keywords = $keyword;

$this->_indexName = $indexName;

return $this;

}

/**

* 字段

*

* @param string $field

* @return $this

*/

public function field($field = '*')

{

$this->conn->SetSelect($field);

return $this;

}

public function getError()

{

return $this->conn->GetLastError();

}

/**

* 给服务器端结果集设置一个偏移量($offset)和从那个偏移量起向客户端返回的匹配项数目限制($limit)。

* 并且可以在服务器端设定当前查询的结果集大小($max_matches),另有一个阈值($cutoff),当找到的匹配项达到这个阀值时就停止搜索。

* 全部这些参数都必须是非负整数。

*

* @param $page

* @param int $itemPerPage

* @param int $maxMatches

* @param int $cutoff

* @return $this

*/

public function limit($page, $itemPerPage = 20, $maxMatches = 1000, $cutoff = 0)

{

$this->_page['page'] = ($page - 1) * $itemPerPage;

$this->_page['item_per_page'] = $itemPerPage;

$this->conn->SetLimits($this->_page['page'], $this->_page['item_per_page'], $maxMatches, $cutoff);

return $this;

}

/**

* 排序

*

* @param $field

* @param string $orderBy

* @return $this

* @throws Exception

*/

public function order($field, $orderBy = 'asc')

{

if (empty($field)) {

throw new Exception('order error: field is null');

}

$this->conn->SetSortMode(SPH_SORT_EXTENDED, "{$field} $orderBy");

return $this;

}

/**

* 获得数据

*

* @param bool $filter

* @return array

*/

public function get($filter = true)

{

$this->_data = $this->conn->query($this->_keywords, $this->_indexName);

return $filter ? $this->_filterData() : $this->_data;

}

/**

* 过滤结果数据

*

* @return array

*/

private function _filterData()

{

$itemList = [];

if (!empty($this->_data['total'])) {

$data = array_values($this->_data['matches']);

foreach ($data as $value) {

$itemList[] = array_merge(['id' => $value['id']],$value['attrs']);

}

$itemPerPage = min(50, $this->_page['item_per_page']);

$pageCount = ceil($this->_data['total'] / $itemPerPage);

$this->_page['page_count'] = $pageCount;

$this->_page['item_count'] = $this->_data['total'];

$this->_page['item_list'] = $itemList;

$this->_page['words'] = $this->_data['words'];

}

return $this->_data = $this->_page;

}

}

//使用方法也很简单

$sphinx = Sphinx::Instance()->init();

$result = $search->query($keyWord, $indexName)->limit($page, $itemPerPage)->order('ctime','desc')->field($field)->get();

参考文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值